[med-svn] [qsopt-ex] 01/03: Imported Upstream version 2.5.10.3+ds
Afif Elghraoui
afif-guest at moszumanska.debian.org
Thu Jan 21 09:19:33 UTC 2016
This is an automated email from the git hooks/post-receive script.
afif-guest pushed a commit to branch master
in repository qsopt-ex.
commit 4fcec2f79fa924d61b0c860b837d74fe13505883
Author: Afif Elghraoui <afif at ghraoui.name>
Date: Fri Oct 9 01:57:14 2015 -0700
Imported Upstream version 2.5.10.3+ds
---
.gitignore | 56 +
.travis.yml | 11 +
Doxyfile | 1201 ++++++++++
License.txt | 674 ++++++
Makefile.am | 240 ++
NEWS.md | 40 +
README.md | 91 +
bootstrap | 6 +
configure.ac | 123 +
esolver/esolver.c | 391 +++
m4/README | 3 +
qsopt_ex/QSopt_ex.h | 114 +
qsopt_ex/QSopt_ex_version.c | 33 +
qsopt_ex/QSopt_ex_version.h | 26 +
qsopt_ex/allocrus.c | 284 +++
qsopt_ex/allocrus.h | 241 ++
qsopt_ex/basicdefs.h | 386 +++
qsopt_ex/basis.c | 1554 ++++++++++++
qsopt_ex/basis.h | 99 +
qsopt_ex/bgetopt.c | 132 +
qsopt_ex/bgetopt.h | 43 +
qsopt_ex/binary.c | 1756 ++++++++++++++
qsopt_ex/binary.h | 36 +
qsopt_ex/dheaps_i.c | 347 +++
qsopt_ex/dheaps_i.h | 72 +
qsopt_ex/dstruct.c | 499 ++++
qsopt_ex/dstruct.h | 134 ++
qsopt_ex/editor.c | 789 ++++++
qsopt_ex/editor.h | 35 +
qsopt_ex/eg_elist.h | 229 ++
qsopt_ex/eg_exact.h | 41 +
qsopt_ex/eg_exutil.c | 485 ++++
qsopt_ex/eg_exutil.h | 317 +++
qsopt_ex/eg_io.c | 695 ++++++
qsopt_ex/eg_io.h | 338 +++
qsopt_ex/eg_lpnum.c | 905 +++++++
qsopt_ex/eg_lpnum.dbl.h | 488 ++++
qsopt_ex/eg_lpnum.h | 706 ++++++
qsopt_ex/eg_lpnum.mpf.h | 628 +++++
qsopt_ex/eg_lpnum.mpq.h | 596 +++++
qsopt_ex/eg_macros.c | 148 ++
qsopt_ex/eg_macros.h | 270 +++
qsopt_ex/eg_mem.h | 194 ++
qsopt_ex/eg_memslab.c | 327 +++
qsopt_ex/eg_memslab.h | 418 ++++
qsopt_ex/eg_nummacros.h | 81 +
qsopt_ex/eg_numutil.c | 106 +
qsopt_ex/eg_numutil.h | 97 +
qsopt_ex/eg_timer.h | 143 ++
qsopt_ex/exact.c | 1824 ++++++++++++++
qsopt_ex/exact.h | 361 +++
qsopt_ex/except.c | 54 +
qsopt_ex/except.h | 170 ++
qsopt_ex/factor.c | 5602 +++++++++++++++++++++++++++++++++++++++++++
qsopt_ex/factor.h | 206 ++
qsopt_ex/fct.c | 2501 +++++++++++++++++++
qsopt_ex/fct.h | 250 ++
qsopt_ex/format.c | 231 ++
qsopt_ex/format.h | 137 ++
qsopt_ex/lib.c | 4348 +++++++++++++++++++++++++++++++++
qsopt_ex/lib.h | 150 ++
qsopt_ex/logging-private.h | 261 ++
qsopt_ex/logging.c | 82 +
qsopt_ex/logging.h | 26 +
qsopt_ex/lp.c | 1280 ++++++++++
qsopt_ex/lp.h | 74 +
qsopt_ex/lpdata.c | 744 ++++++
qsopt_ex/lpdata.h | 303 +++
qsopt_ex/lpdefs.h | 330 +++
qsopt_ex/mps.c | 1350 +++++++++++
qsopt_ex/mps.h | 53 +
qsopt_ex/names.c | 102 +
qsopt_ex/names.h | 35 +
qsopt_ex/presolve.c | 2634 ++++++++++++++++++++
qsopt_ex/presolve.h | 41 +
qsopt_ex/price.c | 1640 +++++++++++++
qsopt_ex/price.h | 222 ++
qsopt_ex/priority.c | 259 ++
qsopt_ex/priority.h | 75 +
qsopt_ex/qs_config.h | 70 +
qsopt_ex/qsopt.c | 3933 ++++++++++++++++++++++++++++++
qsopt_ex/qsopt.h | 358 +++
qsopt_ex/qstruct.h | 49 +
qsopt_ex/ratio.c | 1297 ++++++++++
qsopt_ex/ratio.h | 73 +
qsopt_ex/rawlp.c | 1765 ++++++++++++++
qsopt_ex/rawlp.h | 259 ++
qsopt_ex/read_lp.c | 837 +++++++
qsopt_ex/read_lp.h | 148 ++
qsopt_ex/read_mps.c | 522 ++++
qsopt_ex/read_mps.h | 97 +
qsopt_ex/reader.c | 283 +++
qsopt_ex/reader.h | 33 +
qsopt_ex/readline.c | 62 +
qsopt_ex/readline.h | 64 +
qsopt_ex/reporter.c | 94 +
qsopt_ex/reporter.h | 59 +
qsopt_ex/simplex.c | 3026 +++++++++++++++++++++++
qsopt_ex/simplex.h | 89 +
qsopt_ex/sortrus.c | 289 +++
qsopt_ex/sortrus.h | 44 +
qsopt_ex/sortrus_common.c | 426 ++++
qsopt_ex/sortrus_common.h | 63 +
qsopt_ex/stddefs.h | 34 +
qsopt_ex/symtab.c | 969 ++++++++
qsopt_ex/symtab.h | 141 ++
qsopt_ex/trace.h | 41 +
qsopt_ex/urandom.c | 169 ++
qsopt_ex/urandom.h | 59 +
qsopt_ex/util.c | 283 +++
qsopt_ex/util.h | 152 ++
qsopt_ex/write_lp.c | 262 ++
qsopt_ex/write_lp.h | 73 +
qsopt_ex/zeit.c | 292 +++
qsopt_ex/zeit.h | 65 +
tap-driver.sh | 651 +++++
tests/eg_lpnum_ex.c | 297 +++
tests/eg_sloan.c | 243 ++
tests/eg_sloan.h | 9 +
tests/ftest.c | 303 +++
tests/ftest.h | 21 +
tests/solver.c | 356 +++
tests/solver.h | 33 +
tests/test_qs.c | 243 ++
124 files changed, 60609 insertions(+)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0c5a244
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,56 @@
+# Object files
+*.o
+*.ko
+*.obj
+*.elf
+
+# Precompiled Headers
+*.gch
+*.pch
+
+# Libraries
+*.lib
+*.a
+*.la
+*.lo
+
+# Shared objects (inc. Windows DLLs)
+*.dll
+*.so
+*.so.*
+*.dylib
+
+# Executables
+*.exe
+*.out
+*.app
+*.i*86
+*.x86_64
+*.hex
+
+# http://www.gnu.org/software/automake
+
+.deps
+.dirstamp
+Makefile
+Makefile.in
+
+/test-driver
+
+# http://www.gnu.org/software/autoconf
+
+/autom4te.cache
+/aclocal.m4
+/compile
+/configure
+/depcomp
+/install-sh
+/ltmain.sh
+/m4/*.m4
+/missing
+/stamp-h1
+/config.guess
+/config.h*
+/config.log
+/config.status
+/config.sub
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..0349c6d
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,11 @@
+language: c
+compiler:
+ - gcc
+ - clang
+before_install:
+ - sed -i -e 's|AC_PREREQ(2.69)|AC_PREREQ(2.68)|' configure.ac
+ - sudo apt-get update -qq
+install:
+ - sudo apt-get install -qq libgmp-dev libgmp10
+script: >
+ ./bootstrap && ./configure && make -j2 distcheck
diff --git a/Doxyfile b/Doxyfile
new file mode 100644
index 0000000..6c9ddee
--- /dev/null
+++ b/Doxyfile
@@ -0,0 +1,1201 @@
+# Doxyfile 1.4.3
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = QSopt_ex
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = 050502
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = doc
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish,
+# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese,
+# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish,
+# Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = YES
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = YES
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = YES
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 2
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
+# only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = YES
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = YES
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = YES
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = YES
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 300
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation.
+
+SHOW_DIRECTORIES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from the
+# version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the progam writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE = doxygen.log
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT =
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm
+
+FILE_PATTERNS = *.c \
+ *.h
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = YES
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE = EGlib
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+
+EXCLUDE_PATTERNS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH = . EGlib
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = NO
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = YES
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = YES
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = YES
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = YES
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 150
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = yes
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = YES
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = letter
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES = pst-all amsmath amssymb algorithmic
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = /home/daespino/man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .9
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = NO
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES = EGlib/EGlib_Doxygen_Tags=http://www.dii.uchile.cl/~daespino/EGlib_doc
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE = ESolver_Doxygen_Tags
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = YES
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = YES
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH = YES
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = gif
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that a graph may be further truncated if the graph's
+# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH
+# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default),
+# the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, which results in a white background.
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
diff --git a/License.txt b/License.txt
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/License.txt
@@ -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/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..58fdab7
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,240 @@
+
+ACLOCAL_AMFLAGS = -I m4
+
+# These source files are used as is for the library
+MAIN_SOURCE_FILES = \
+ qsopt_ex/allocrus.c \
+ qsopt_ex/bgetopt.c \
+ qsopt_ex/eg_io.c \
+ qsopt_ex/eg_lpnum.c \
+ qsopt_ex/except.c \
+ qsopt_ex/urandom.c \
+ qsopt_ex/zeit.c \
+ qsopt_ex/names.c \
+ qsopt_ex/symtab.c \
+ qsopt_ex/util.c \
+ qsopt_ex/logging.c \
+ qsopt_ex/exact.c \
+ qsopt_ex/reporter.c \
+ qsopt_ex/eg_exutil.c \
+ qsopt_ex/eg_macros.c \
+ qsopt_ex/eg_memslab.c \
+ qsopt_ex/sortrus_common.c \
+ qsopt_ex/QSopt_ex_version.c
+
+# Header files
+PUBLIC_HEADER_FILES = \
+ qsopt_ex/bgetopt.h \
+ qsopt_ex/eg_io.h \
+ qsopt_ex/eg_lpnum.h \
+ qsopt_ex/urandom.h \
+ qsopt_ex/zeit.h \
+ qsopt_ex/names.h \
+ qsopt_ex/symtab.h \
+ qsopt_ex/exact.h \
+ qsopt_ex/reporter.h \
+ qsopt_ex/eg_exutil.h \
+ qsopt_ex/eg_macros.h \
+ qsopt_ex/eg_memslab.h \
+ qsopt_ex/eg_mem.h \
+ qsopt_ex/eg_elist.h \
+ qsopt_ex/eg_nummacros.h \
+ qsopt_ex/eg_lpnum.dbl.h \
+ qsopt_ex/eg_lpnum.mpq.h \
+ qsopt_ex/eg_lpnum.mpf.h \
+ qsopt_ex/eg_timer.h \
+ qsopt_ex/basicdefs.h \
+ qsopt_ex/stddefs.h \
+ qsopt_ex/sortrus_common.h \
+ qsopt_ex/QSopt_ex_version.h \
+ qsopt_ex/QSopt_ex.h \
+ qsopt_ex/logging.h
+
+PRIVATE_HEADER_FILES = \
+ qsopt_ex/allocrus.h \
+ qsopt_ex/except.h \
+ qsopt_ex/logging-private.h \
+ qsopt_ex/logging.h \
+ qsopt_ex/qs_config.h \
+ qsopt_ex/trace.h \
+ qsopt_ex/util.h
+
+# These source files have to be instantiated using the
+# type template mechanism
+TEMPLATE_SOURCE_FILES = \
+ qsopt_ex/rawlp.c \
+ qsopt_ex/mps.c \
+ qsopt_ex/read_mps.c \
+ qsopt_ex/lp.c \
+ qsopt_ex/write_lp.c \
+ qsopt_ex/read_lp.c \
+ qsopt_ex/readline.c \
+ qsopt_ex/lpdata.c \
+ qsopt_ex/presolve.c \
+ qsopt_ex/factor.c \
+ qsopt_ex/basis.c \
+ qsopt_ex/price.c \
+ qsopt_ex/dstruct.c \
+ qsopt_ex/simplex.c \
+ qsopt_ex/fct.c \
+ qsopt_ex/ratio.c \
+ qsopt_ex/lib.c \
+ qsopt_ex/binary.c \
+ qsopt_ex/qsopt.c \
+ qsopt_ex/sortrus.c \
+ qsopt_ex/dheaps_i.c \
+ qsopt_ex/priority.c \
+ qsopt_ex/editor.c \
+ qsopt_ex/format.c \
+ qsopt_ex/eg_numutil.c
+
+TEMPLATE_PUBLIC_HEADER_FILES = \
+ qsopt_ex/write_lp.h \
+ qsopt_ex/read_lp.h \
+ qsopt_ex/read_mps.h \
+ qsopt_ex/readline.h \
+ qsopt_ex/lpdata.h \
+ qsopt_ex/presolve.h \
+ qsopt_ex/factor.h \
+ qsopt_ex/basis.h \
+ qsopt_ex/price.h \
+ qsopt_ex/dstruct.h \
+ qsopt_ex/simplex.h \
+ qsopt_ex/fct.h \
+ qsopt_ex/ratio.h \
+ qsopt_ex/lib.h \
+ qsopt_ex/binary.h \
+ qsopt_ex/qsopt.h \
+ qsopt_ex/sortrus.h \
+ qsopt_ex/dheaps_i.h \
+ qsopt_ex/priority.h \
+ qsopt_ex/editor.h \
+ qsopt_ex/format.h \
+ qsopt_ex/lpdefs.h \
+ qsopt_ex/qstruct.h \
+ qsopt_ex/eg_numutil.h
+
+TEMPLATE_PRIVATE_HEADER_FILES = \
+ qsopt_ex/rawlp.h \
+ qsopt_ex/mps.h \
+ qsopt_ex/lp.h
+
+# Define specific template sources
+TEMPLATE_SOURCES_DBL = $(TEMPLATE_SOURCE_FILES:.c=_dbl.c)
+TEMPLATE_PUBLIC_HEADERS_DBL = \
+ $(TEMPLATE_PUBLIC_HEADER_FILES:.h=_dbl.h)
+TEMPLATE_HEADERS_DBL = \
+ $(TEMPLATE_PUBLIC_HEADERS_DBL) \
+ $(TEMPLATE_PRIVATE_HEADER_FILES:.h=_dbl.h)
+
+$(TEMPLATE_SOURCES_DBL): %_dbl.c: %.c Makefile
+ $(AM_V_GEN)$(MKDIR_P) $(@D) && ( \
+ echo "/* WARNING! This file was autogenerated from template */" && \
+ $(SED) -e 's|EGLPNUM_TYPENAME|dbl|g' -e 's|EGLPNUM_TYPE|double|g' $< ) > $@
+$(TEMPLATE_HEADERS_DBL): %_dbl.h: %.h Makefile
+ $(AM_V_GEN)$(MKDIR_P) $(@D) && ( \
+ echo "/* WARNING! This file was autogenerated from template */" && \
+ $(SED) -e 's|EGLPNUM_TYPENAME|dbl|g' -e 's|EGLPNUM_TYPE|double|g' $< ) > $@
+
+TEMPLATE_SOURCES_MPQ = $(TEMPLATE_SOURCE_FILES:.c=_mpq.c)
+TEMPLATE_PUBLIC_HEADERS_MPQ = \
+ $(TEMPLATE_PUBLIC_HEADER_FILES:.h=_mpq.h)
+TEMPLATE_HEADERS_MPQ = \
+ $(TEMPLATE_PUBLIC_HEADERS_MPQ) \
+ $(TEMPLATE_PRIVATE_HEADER_FILES:.h=_mpq.h)
+
+$(TEMPLATE_SOURCES_MPQ): %_mpq.c: %.c Makefile
+ $(AM_V_GEN)$(MKDIR_P) $(@D) && ( \
+ echo "/* WARNING! This file was autogenerated from template */" && \
+ $(SED) -e 's|EGLPNUM_TYPENAME|mpq|g' -e 's|EGLPNUM_TYPE|mpq_t|g' $< ) > $@
+$(TEMPLATE_HEADERS_MPQ): %_mpq.h: %.h Makefile
+ $(AM_V_GEN)$(MKDIR_P) $(@D) && ( \
+ echo "/* WARNING! This file was autogenerated from template */" && \
+ $(SED) -e 's|EGLPNUM_TYPENAME|mpq|g' -e 's|EGLPNUM_TYPE|mpq_t|g' $< ) > $@
+
+TEMPLATE_SOURCES_MPF = $(TEMPLATE_SOURCE_FILES:.c=_mpf.c)
+TEMPLATE_PUBLIC_HEADERS_MPF = \
+ $(TEMPLATE_PUBLIC_HEADER_FILES:.h=_mpf.h)
+TEMPLATE_HEADERS_MPF = \
+ $(TEMPLATE_PUBLIC_HEADERS_MPF) \
+ $(TEMPLATE_PRIVATE_HEADER_FILES:.h=_mpf.h)
+
+$(TEMPLATE_SOURCES_MPF): %_mpf.c: %.c Makefile
+ $(AM_V_GEN)$(MKDIR_P) $(@D) && ( \
+ echo "/* WARNING! This file was autogenerated from template */" && \
+ $(SED) -e 's|EGLPNUM_TYPENAME|mpf|g' -e 's|EGLPNUM_TYPE|mpf_t|g' $< ) > $@
+$(TEMPLATE_HEADERS_MPF): %_mpf.h: %.h Makefile
+ $(AM_V_GEN)$(MKDIR_P) $(@D) && ( \
+ echo "/* WARNING! This file was autogenerated from template */" && \
+ $(SED) -e 's|EGLPNUM_TYPENAME|mpf|g' -e 's|EGLPNUM_TYPE|mpf_t|g' $< ) > $@
+
+# Define complete set of template files
+TEMPLATE_FILES = \
+ $(TEMPLATE_SOURCES_DBL) $(TEMPLATE_HEADERS_DBL) \
+ $(TEMPLATE_SOURCES_MPQ) $(TEMPLATE_HEADERS_MPQ) \
+ $(TEMPLATE_SOURCES_MPF) $(TEMPLATE_HEADERS_MPF)
+
+# Tell automake that these are generated files
+BUILT_SOURCES = $(TEMPLATE_FILES)
+
+
+AM_CFLAGS = -I$(top_srcdir)/qsopt_ex -I$(top_builddir)/qsopt_ex
+
+# Library files
+lib_LTLIBRARIES = libqsopt_ex.la
+libqsopt_ex_la_SOURCES = \
+ $(MAIN_SOURCE_FILES) $(PUBLIC_HEADER_FILES) \
+ $(PRIVATE_HEADER_FILES)
+nodist_libqsopt_ex_la_SOURCES = \
+ $(TEMPLATE_FILES)
+libqsopt_ex_la_CFLAGS = \
+ $(AM_CFLAGS) $(GMP_CFLAGS)
+libqsopt_ex_la_LDFLAGS = \
+ -no-undefined \
+ -version-info $(LT_VERSION_INFO) \
+ $(AM_LDFLAGS)
+libqsopt_ex_la_LIBADD = $(GMP_LIBS)
+
+# Library header files
+headerdir = $(includedir)/qsopt_ex
+header_DATA = \
+ $(PUBLIC_HEADER_FILES) \
+ $(TEMPLATE_PUBLIC_HEADERS_DBL) \
+ $(TEMPLATE_PUBLIC_HEADERS_MPQ) \
+ $(TEMPLATE_PUBLIC_HEADERS_MPF)
+
+
+# Program files
+bin_PROGRAMS = esolver/esolver
+noinst_PROGRAMS = tests/test_qs tests/eg_sloan
+
+tests_test_qs_SOURCES = tests/test_qs.c
+tests_test_qs_CFLAGS = $(AM_CFLAGS) $(GMP_CFLAGS)
+tests_test_qs_LDADD = $(GMP_LIBS) libqsopt_ex.la
+
+tests_eg_sloan_SOURCES = tests/eg_sloan.c tests/eg_sloan.h
+tests_eg_sloan_CFLAGS = $(AM_CFLAGS) $(GMP_CFLAGS)
+tests_eg_sloan_LDADD = $(GMP_LIBS) libqsopt_ex.la
+
+esolver_esolver_SOURCES = esolver/esolver.c
+esolver_esolver_CFLAGS = $(AM_CFLAGS) $(GMP_CFLAGS)
+esolver_esolver_LDADD = $(GMP_LIBS) libqsopt_ex.la
+
+
+# Tests
+LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) \
+ $(top_srcdir)/tap-driver.sh
+TESTS = tests/test_qs
+
+
+# Additional files to be distributed. Always run `make distcheck`
+# to be sure all necessary files are distributed!
+EXTRA_DIST = \
+ README.md NEWS.md Doxyfile License.txt \
+ $(TEMPLATE_SOURCE_FILES) \
+ $(TEMPLATE_PUBLIC_HEADER_FILES) \
+ $(TEMPLATE_PRIVATE_HEADER_FILES)
+
+# Clean files
+CLEANFILES = \
+ $(TEMPLATE_FILES)
diff --git a/NEWS.md b/NEWS.md
new file mode 100644
index 0000000..c610a70
--- /dev/null
+++ b/NEWS.md
@@ -0,0 +1,40 @@
+
+2.5.10.3
+--------
+- All output to stdout/stderr now goes through an internal logging function.
+ The log messages can optionally be redirected to a user supplied function
+ (by default they are written to stderr).
+- Some headers that are internal to the library are no longer installed.
+- Restored possibility of compressing the output files (Denis Rosset).
+- Remove unused support for dmalloc.
+- Convert demo_qs into test_qs TAP test suite.
+
+2.5.10.2
+--------
+* (The patch `_p` version notation used in 2.5.10_p1 is not widely supported so
+ this release simply uses the dot notation.)
+* Removes Python module (moved to separate repository at
+ https://github.com/jonls/python-qsoptex).
+* Move library source files into `qsopt_ex` so the header files can be accessed
+ in the same way as when installed (`<qsopt_ex/XX.h>`).
+* Explicitly include the typename of template types when using a macro,
+ variable or function that is template generated. This removes the
+ build dependencies on Exuberant Ctags and GNU sed, as well as speeding up
+ the template generation significantly.
+* Remove util.c/util.h from template generation since the majority of symbols
+ are not template type specific.
+
+2.5.10_p1
+---------
+* Based on original version v2.5.10 published by Daniel Espinoza et al.
+* Changed to autotools-based build system.
+* Removed external dependency on EGlib.
+* Build library using libtool for portability.
+* Add Cython-based Python module to interface with libqsopt_ex.
+* Fix sprintf calls with missing format string.
+* Add missing header declarations, includes.
+* Clean up headers to make external use easier.
+* Remove some unused functions/macros that caused compiler warnings/errors.
+* Workaround: Writing solution to gz-file was broken; temporarily disabled gzip output.
+* Add README file with build instructions and code examples.
+* Add Travis CI build script.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..6b98b21
--- /dev/null
+++ b/README.md
@@ -0,0 +1,91 @@
+
+QSopt Exact
+===========
+
+[![Build Status](https://travis-ci.org/jonls/qsopt-ex.svg?branch=master)](https://travis-ci.org/jonls/qsopt-ex)
+
+Exact linear programming solver. This is a fork of QSopt_ex, originally
+released by Daniel Espinoza _et al._
+[version 2.5.10](http://www.math.uwaterloo.ca/~bico/qsopt/ex/) under the
+GPL 3 (or later). The authors of QSopt_ex also granted a free license to
+use the software for research purposes but this license does not extend
+to the changes introduced by this project.
+
+The goal of this fork is to update the software, and in particular the
+build system, to be more friendly. In addition the external
+dependencies have been reduced by removing the dependency on EGlib,
+GNU awk and Exuberant Ctags.
+
+Dependencies
+------------
+
+- C compiler: Tested with GCC and Clang.
+- Libtool: To build QSopt_ex as a library.
+- [GNU MP](https://gmplib.org/): Tested with 6.0.0. The original authors
+ stated that QSopt_ex was tested with the 4.x.x and with 5.0.x version
+ series. The authors also noted that GNU MP should be compiled using option
+ `--enable-alloca=malloc-reentrant` but this does not seem to be required
+ anymore.
+- libz: To read/write gz-compresed files.
+- libbz2 To read/write bz2-compresed files.
+
+Installing
+----------
+
+If you have just cloned the source code with Git, run the `bootstrap`
+script to automatically set up the build system.
+
+``` shell
+$ ./bootstrap
+```
+
+This script calls `autoreconf` and `libtoolize` with the proper
+arguments. This will also regenerate the `configure` script. It is
+recommended to build out of source directory. This is simply done
+by running `configure` from an empty directory.
+
+``` shell
+$ mkdir build && cd build
+$ ../configure
+```
+
+Use `./configure --help` to see available options. Now the test
+programs and library can be compiled using `make`. It is possible
+to do a parallel build using the `-jX` switch where `X` is the number
+of parallel processes.
+
+``` shell
+$ make -j4
+```
+
+To install the libraries and executables run
+
+``` shell
+$ make install
+```
+
+This will install into the prefix specified when `configure` was run.
+
+Running the solver
+------------------
+
+The exact solver is available though the `esolver` executable. It can be
+invoked to solve an LP or MPS format problem.
+
+``` shell
+$ ./esolver cycle.mps
+```
+
+See `./esolver -h` for more information on command line options.
+
+Using it as a library
+---------------------
+To see an example of how to use this software as a C library, see the test
+[tests/test_qs.c](tests/test_qs.c) or the program
+[esolver/esolver.c](esolver/esolver.c).
+
+Python module
+-------------
+
+The Python module has moved to a separate repository at
+[jonls/python-qsoptex](https://github.com/jonls/python-qsoptex).
diff --git a/bootstrap b/bootstrap
new file mode 100755
index 0000000..8724a10
--- /dev/null
+++ b/bootstrap
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+# change to root directory
+cd $(dirname "$0")
+
+autoreconf --force --install --verbose
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..e99e21d
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,123 @@
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+
+AC_PREREQ(2.69)
+AC_INIT([QSopt_ex], [2.5.10.3], [https://github.com/jonls/qsopt-ex/issues])
+AC_CONFIG_SRCDIR([qsopt_ex/QSopt_ex.h])
+AC_CONFIG_HEADERS([config.h])
+AC_CONFIG_MACRO_DIR([m4])
+AC_REQUIRE_AUX_FILE([tap-driver.sh])
+AM_INIT_AUTOMAKE([foreign subdir-objects dist-xz])
+
+m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+
+AC_USE_SYSTEM_EXTENSIONS
+
+### Versioning
+# This is the internal library version information used by libtool.
+# IT DOES NOT FOLLOW THE NORMAL RELEASE VERSIONING!
+# Instead follow these rules from the libtool documentation:
+# 1. Update the version information only immediately before a public release of your software.
+# 2. If the library source code has changed at all since the last update, then increment revision.
+# ("c:r:a" becomes "c:r+1:a")
+# 3. If any interfaces have been added, removed, or changed since the last update, increment current,
+# and set revision to 0. ("c+1:0:a")
+# 4. If any interfaces have been added since the last public release, then increment age.
+# 5. If any interfaces have been removed since the last public release, then set age to 0.
+
+m4_define([lt_current],[3])
+m4_define([lt_revision],[0])
+m4_define([lt_age],[1])
+m4_define([lt_version_info],[lt_current:lt_revision:lt_age])
+AC_SUBST([LT_VERSION_INFO], [lt_version_info])
+
+### Checks for programs.
+AC_PROG_CC
+AC_PROG_SED
+AC_PROG_LIBTOOL
+
+
+### Check for debug mode
+AC_ARG_ENABLE([debug],
+ [AS_HELP_STRING([--enable-debug], [enable debug mode @<:@default=yes@:>@])],
+ [enable_debug=$enable])
+AS_IF([test "x$enable_debug" != xno], [
+ AC_SUBST([ENABLE_DEBUG],[1])
+ AC_DEFINE([DEBUG], [1], [Enable debug mode])
+], [
+ AC_SUBST([ENABLE_DEBUG],[0])
+ AC_DEFINE([DEBUG], [0], [Disable debug mode])
+])
+
+### Check for verbosity level
+AC_ARG_ENABLE([verbose-level],
+ [AS_HELP_STRING([--enable-verbose-level], [fix verbose-level for compile-time routines @<:@default=100@:>@])],
+ [],[enable_verbose_level=100])
+AC_DEFINE_UNQUOTED([VERBOSE_LEVEL],[$enable_verbose_level],[Compilation-time verbose level])
+
+### Check for libgmp
+AC_ARG_VAR([GMP_CFLAGS], [C compiler flags for GMP, overriding automatic detection])
+AC_ARG_VAR([GMP_LIBS], [linker flags for GMP, overriding automatic detection])
+AS_IF([test -z "$GMP_CFLAGS" -a -z "$GMP_LIBS"], [
+ AC_CHECK_LIB([gmp], [__gmpz_init], [
+ GMP_CFLAGS=""
+ GMP_LIBS="-lgmp"
+ ], [AC_MSG_ERROR([GNU MP not found, see https://gmplib.org/])])
+])
+
+### Check for libz
+AC_CHECK_LIB([z], [gzopen], [], AC_MSG_NOTICE([compiling without libz]))
+
+### Check for libbz2
+AC_CHECK_LIB([bz2], [BZ2_bzopen], [], AC_MSG_NOTICE([compiling without libbz2]))
+
+### Check for math library
+AC_SEARCH_LIBS([pow], [m], [], [
+ AC_MSG_ERROR([unable to find library with math functions (pow)])])
+
+### Check for pthread library
+AC_CHECK_LIB([pthread], [pthread_mutex_lock])
+
+### Checks for header files.
+AC_HEADER_STDC
+AC_HEADER_TIME
+AC_CHECK_HEADERS([errno.h float.h getopt.h inttypes.h limits.h math.h setjmp.h signal.h stdarg.h stdint.h stdio.h string.h sys/param.h sys/resource.h sys/time.h sys/times.h sys/utsname.h unistd.h])
+
+### Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_C_TYPEOF
+AC_TYPE_INT16_T
+AC_TYPE_INT32_T
+AC_TYPE_INT64_T
+AC_TYPE_INT8_T
+AC_TYPE_SIGNAL
+AC_TYPE_SIZE_T
+AC_TYPE_SSIZE_T
+AC_TYPE_UINT16_T
+AC_TYPE_UINT32_T
+AC_TYPE_UINT64_T
+AC_TYPE_UINT8_T
+
+### Checks for library functions.
+AC_FUNC_MALLOC
+AC_FUNC_MEMCMP
+AC_FUNC_REALLOC
+AC_FUNC_STRTOD
+AC_FUNC_VPRINTF
+AC_CHECK_FUNCS([floor memset pow sqrt strdup strerror uname posix_memalign sleep getrusage times clock sigaction signal])
+
+### Print output files
+AC_CONFIG_FILES([
+ Makefile
+])
+AC_OUTPUT
+
+
+echo "
+ $PACKAGE_NAME $VERSION
+
+ prefix: ${prefix}
+ compiler: ${CC}
+ cflags: ${CFLAGS}
+ ldflags: ${LDFLAGS}
+"
diff --git a/esolver/esolver.c b/esolver/esolver.c
new file mode 100644
index 0000000..6694518
--- /dev/null
+++ b/esolver/esolver.c
@@ -0,0 +1,391 @@
+/* ========================================================================= */
+/* ESolver "Exact Mixed Integer Linear Solver" provides some basic structures
+ * and algorithms commons in solving MIP's
+ *
+ * Copyright (C) 2008 David Applegate, Bill Cook, Sanjeeb Dash, Daniel Espinoza.
+ *
+ * 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
+ * */
+/* ========================================================================= */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <signal.h>
+#include <limits.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include "QSopt_ex.h"
+
+#include "except.h"
+#include "logging-private.h"
+#include "qs_config.h"
+
+/* ========================================================================= */
+/** @name static parameters for the main program */
+/*@{*/
+static char *fname = 0;
+static int lpfile = 0;
+static int usescaling = 1;
+static int showversion = 0;
+static int simplexalgo = PRIMAL_SIMPLEX;
+static int pstrategy = QS_PRICE_PSTEEP;
+static int dstrategy = QS_PRICE_DSTEEP;
+static unsigned precision = 128;
+static int printsol = 0;
+static char *solname = 0;
+static char *readbasis = 0;
+static char *writebasis = 0;
+/** @brief maximum running time */
+static double max_rtime = INT_MAX;
+/** @brief maximum memory usage */
+static unsigned long memlimit = UINT_MAX;
+/*@}*/
+/* ========================================================================= */
+/** @brief Display options to the screen */
+static void usage (char *s)
+{
+ fprintf (stderr, "Usage: %s [- below -] prob_file\n", s);
+ fprintf (stderr, " -b f write basis to file f\n");
+ fprintf (stderr, " -B f read initial basis from file f\n");
+#if 0
+ fprintf (stderr, " -I solve the MIP using BestBound\n");
+ fprintf (stderr, " -E edit problem after solving initial version\n");
+#endif
+ fprintf (stderr, " -L input file is in lp format (default: mps)\n");
+ fprintf (stderr, " -O write the final solution to the given file\n");
+ fprintf (stderr, " append .gz/.bz2 to the .sol extension to compress the file\n");
+ fprintf (stderr, " -p # run primal simplex with pricing rule #\n");
+ fprintf (stderr,
+ " (%d-Dantzig, %d-Devex, %d-Steep (default), %d-Partial\n",
+ QS_PRICE_PDANTZIG, QS_PRICE_PDEVEX, QS_PRICE_PSTEEP,
+ QS_PRICE_PMULTPARTIAL);
+ fprintf (stderr,
+ " -P # number of bits to use for the float representation (default: 128)\n");
+ fprintf (stderr, " -d # run dual simplex with pricing rule #\n");
+ fprintf (stderr, " (%d-Dantzig, %d-Steep, %d-Partial, %d-Devex)\n",
+ QS_PRICE_DDANTZIG, QS_PRICE_DSTEEP, QS_PRICE_DMULTPARTIAL,
+ QS_PRICE_DDEVEX);
+ fprintf (stderr, " -S do NOT scale the initial LP\n");
+ fprintf (stderr, " -v print QSopt version number\n");
+ fprintf (stderr, " -R n maximum running time allowed, default %lf\n",
+ max_rtime);
+ fprintf (stderr, " -m n maximum memory usage allowed, default %lu\n",
+ memlimit);
+}
+
+/* ========================================================================= */
+/** @brief decide if a given file is mps or lp (only by extension) */
+static void get_ftype (char const *const name,
+ int *ftype)
+{
+ char buff[4096],*argv[128];
+ int argc;
+ *ftype = 0; /* by default, file is MPS */
+ snprintf(buff,4096,"%s",name);
+ EGioNParse(buff,128,"."," ",&argc,argv);
+ argc-=1;
+ if(argc)
+ {
+ if(strncmp(argv[argc],"gz",3)==0) argc-=1;
+ else if(strncmp(argv[argc],"GZ",3)==0) argc-=1;
+ else if(strncmp(argv[argc],"bz2",4)==0) argc-=1;
+ else if(strncmp(argv[argc],"BZ2",4)==0) argc-=1;
+ }
+ if(argc)
+ {
+ if(strncmp(argv[argc],"lp",3)==0) *ftype=1;
+ else if(strncmp(argv[argc],"LP",3)==0) *ftype=1;
+ }
+}
+/* ========================================================================= */
+/** @brief signal handler for time-limit reached */
+static void sighandler(int s)
+{
+ switch(s)
+ {
+ case SIGXCPU:
+ fprintf(stderr,"TIME_LIMIT_REACHED (ending now)\n");
+ exit(EXIT_FAILURE);
+ default:
+ fprintf(stderr,"Unknown signal %d (ending now)\n",s);
+ exit(EXIT_FAILURE);
+ }
+}
+/* ========================================================================= */
+/** @brief function to handle resource usage limits */
+static int mem_limits(void)
+{
+ int rval = 0;
+ struct rlimit mlim;
+ rval = getrlimit(RLIMIT_CPU,&mlim);
+ CHECKRVAL(rval);
+ fprintf(stderr, "Cur rtime limit %ld, trying to set to %lg\n", mlim.rlim_cur, max_rtime);
+ if(max_rtime > mlim.rlim_max) max_rtime = (double)mlim.rlim_max;
+ mlim.rlim_cur = (rlim_t)max_rtime;
+ rval = setrlimit(RLIMIT_CPU,&mlim);
+ TESTERRNOIF(rval);
+ fprintf(stderr, "New rtime limit %ld (%.3lg)\n", mlim.rlim_cur, max_rtime);
+ rval = getrlimit(RLIMIT_DATA,&mlim);
+ TESTERRNOIF(rval);
+ fprintf(stderr, "Cur data limit %ld,%ld (soft,hard)\n", mlim.rlim_cur,
+ mlim.rlim_max);
+ mlim.rlim_cur = memlimit;
+ rval = setrlimit(RLIMIT_DATA,&mlim);
+ TESTERRNOIF(rval);
+ rval = getrlimit(RLIMIT_DATA,&mlim);
+ TESTERRNOIF(rval);
+ fprintf(stderr, "New data limit %ld,%ld (soft,hard)\n", mlim.rlim_cur,
+ mlim.rlim_max);
+ rval = getrlimit(RLIMIT_AS,&mlim);
+ TESTERRNOIF(rval);
+ fprintf(stderr, "Cur address space limit %ld,%ld (soft,hard)\n",
+ mlim.rlim_cur, mlim.rlim_max);
+ mlim.rlim_cur = memlimit;
+ rval = setrlimit(RLIMIT_AS,&mlim);
+ TESTERRNOIF(rval);
+ rval = getrlimit(RLIMIT_AS,&mlim);
+ TESTERRNOIF(rval);
+ fprintf(stderr, "New address space limit %ld,%ld (soft,hard)\n",
+ mlim.rlim_cur, mlim.rlim_max);
+ mlim.rlim_cur = 0;
+ rval = setrlimit(RLIMIT_CORE,&mlim);
+ TESTERRNOIF(rval);
+ rval = getrlimit(RLIMIT_CORE,&mlim);
+ TESTERRNOIF(rval);
+ fprintf(stderr, "New core dump space limit %ld,%ld (soft,hard)\n",
+ mlim.rlim_cur, mlim.rlim_max);
+ /* set signal handler for SIGXCPU */
+ signal(SIGXCPU,sighandler);
+ return rval;
+}
+/* ========================================================================= */
+/** @brief parssing options for the program */
+static int parseargs (int ac,
+ char **av)
+{
+ int c;
+ int boptind = 1;
+ char *boptarg = 0;
+
+ while ((c =
+ ILLutil_bix_getopt (ac, av, "b:B:d:EILm:O:p:P:R:Sv", &boptind,
+ &boptarg)) != EOF)
+ switch (c)
+ {
+ case 'm':
+ memlimit = strtoul(boptarg,0,10);
+ break;
+ case 'R':
+ max_rtime = strtod(boptarg,0);
+ break;
+ case 'b':
+ writebasis = boptarg;
+ break;
+ case 'B':
+ readbasis = boptarg;
+ break;
+ case 'P':
+ precision = atoi (boptarg);
+ break;
+ case 'd':
+ simplexalgo = DUAL_SIMPLEX;
+ dstrategy = atoi (boptarg);
+ break;
+ case 'L':
+ lpfile = 1;
+ break;
+ case 'O':
+ printsol = 1;
+ solname = strdup(boptarg);
+ break;
+ case 'p':
+ simplexalgo = PRIMAL_SIMPLEX;
+ pstrategy = atoi (boptarg);
+ break;
+ case 'S':
+ usescaling = 0;
+ break;
+ case 'v':
+ showversion = 1;
+ break;
+ case '?':
+ default:
+ usage (av[0]);
+ return 1;
+ }
+ if ((boptind == ac) && (showversion))
+ {
+ char *buf = 0;
+ buf = mpq_QSversion ();
+ printf ("%s\n", buf);
+ mpq_QSfree ((void *) buf);
+ exit(0);
+ }
+ if (boptind != (ac - 1))
+ {
+ usage (av[0]);
+ return 1;
+ }
+
+ fname = av[boptind++];
+ fprintf (stderr, "Reading problem from %s\n", fname);
+ mem_limits();
+ return 0;
+}
+
+/* ========================================================================= */
+/** @brief the main thing! */
+/* ========================================================================= */
+int main (int ac,
+ char **av)
+{
+ int rval = 0,
+ status = 0;
+ mpq_QSdata *p_mpq = 0;
+ QSbasis *basis = 0;
+ ILLutil_timer timer_solve;
+ ILLutil_timer timer_read;
+ int ftype = 0; /* 0 mps, 1 lp */
+ mpq_t *y_mpq = 0,
+ *x_mpq = 0;
+ QSopt_ex_version();
+ QSexactStart();
+ /* parse arguments and initialize EGlpNum related things */
+ rval = parseargs (ac, av);
+ QSexact_set_precision (precision);
+ if (rval)
+ goto CLEANUP;
+ if (writebasis)
+ {
+ basis = EGsMalloc (QSbasis, 1);
+ memset (basis, 0, sizeof (QSbasis));
+ }
+
+ /* just for the bell's and wistle */
+ if (showversion)
+ {
+ char *buf = 0;
+ buf = mpq_QSversion ();
+ if (buf == 0)
+ {
+ ILL_CLEANUP;
+ }
+ else
+ {
+ printf ("%s\n", buf);
+ mpq_QSfree ((void *) buf);
+ }
+ }
+
+ /* get the file type */
+ if (lpfile)
+ ftype = 1;
+ else
+ get_ftype (fname, &ftype);
+
+ /* read the mpq problem */
+ ILLutil_init_timer (&timer_read, "SOLVER_READ_MPQ");
+ ILLutil_start_timer (&timer_read);
+ if (ftype == 1)
+ {
+ p_mpq = mpq_QSread_prob ((const char *) fname, "LP");
+ if (p_mpq == 0)
+ {
+ fprintf (stderr, "Could not read lp file.\n");
+ rval = 1;
+ ILL_CLEANUP_IF (rval);
+ }
+ }
+ else
+ {
+ p_mpq = mpq_QSread_prob ((const char *) fname, "MPS");
+ if (p_mpq == 0)
+ {
+ fprintf (stderr, "Could not read mps file.\n");
+ rval = 1;
+ ILL_CLEANUP_IF (rval);
+ }
+ }
+
+ /* and get the basis if needed */
+ if (readbasis)
+ {
+ rval = mpq_QSread_and_load_basis (p_mpq, (const char *) readbasis);
+ ILL_CLEANUP_IF (rval);
+ if (basis)
+ mpq_QSfree_basis (basis);
+ basis = mpq_QSget_basis (p_mpq);
+ }
+ ILLutil_stop_timer (&timer_read, 1);
+ /* set the readed flags */
+ rval = mpq_QSset_param (p_mpq, QS_PARAM_SIMPLEX_DISPLAY, 1)
+ || mpq_QSset_param (p_mpq, QS_PARAM_PRIMAL_PRICING, pstrategy)
+ || mpq_QSset_param (p_mpq, QS_PARAM_DUAL_PRICING, dstrategy)
+ || mpq_QSset_param (p_mpq, QS_PARAM_SIMPLEX_SCALING, usescaling);
+ ILL_CLEANUP_IF (rval);
+ if (printsol)
+ {
+ x_mpq = mpq_EGlpNumAllocArray (p_mpq->qslp->ncols);
+ y_mpq = mpq_EGlpNumAllocArray (p_mpq->qslp->nrows);
+ }
+ ILLutil_init_timer (&timer_solve, "SOLVER");
+ ILLutil_start_timer (&timer_solve);
+ rval = QSexact_solver (p_mpq, x_mpq, y_mpq, basis, simplexalgo, &status);
+ ILL_CLEANUP_IF (rval);
+ ILLutil_stop_timer (&timer_solve, 1);
+ if (printsol)
+ {
+ char out_f_name[1024];
+ EGioFile_t *out_f;
+ sprintf (out_f_name, "%s", solname);
+ out_f = EGioOpen (out_f_name, "w");
+ switch (status)
+ {
+ case QS_LP_OPTIMAL:
+ EGioPrintf (out_f, "status = OPTIMAL\n");
+ rval = QSexact_print_sol (p_mpq, out_f);
+ CHECKRVALG(rval,CLEANUP);
+ break;
+ case QS_LP_INFEASIBLE:
+ EGioPrintf (out_f, "status = INFEASIBLE\n");
+ break;
+ case QS_LP_UNBOUNDED:
+ EGioPrintf (out_f, "status = UNBOUNDED\n");
+ break;
+ default:
+ EGioPrintf (out_f, "status = UNDEFINED\n");
+ break;
+ }
+ EGioClose (out_f);
+ }
+ /* ending */
+CLEANUP:
+ EGfree(solname);
+ mpq_EGlpNumFreeArray (x_mpq);
+ mpq_EGlpNumFreeArray (y_mpq);
+ /* free the last allocated basis, and if we wanted to save it, do so */
+ if (basis)
+ {
+ if (writebasis)
+ rval = mpq_QSwrite_basis (p_mpq, 0, writebasis);
+ }
+ mpq_QSfree_basis (basis);
+ mpq_QSfree_prob (p_mpq);
+ QSexactClear();
+ return rval; /* main return */
+}
diff --git a/m4/README b/m4/README
new file mode 100644
index 0000000..120657b
--- /dev/null
+++ b/m4/README
@@ -0,0 +1,3 @@
+This README is here so that git will keep the m4 directory.
+The m4 directory must be here to work around a bug in autotools
+where autoreconf fails if it is not present.
diff --git a/qsopt_ex/QSopt_ex.h b/qsopt_ex/QSopt_ex.h
new file mode 100644
index 0000000..9bea725
--- /dev/null
+++ b/qsopt_ex/QSopt_ex.h
@@ -0,0 +1,114 @@
+/* QSopt_ex.h -- QSopt_ex main header file
+ * This file is part of QSopt_ex.
+ *
+ * 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
+ *
+ * Copyright (c) 2014-2015 Jon Lund Steffensen <jonlst at gmail.com>
+ */
+
+#ifndef QSOPT_EX_H
+#define QSOPT_EX_H
+
+#include "eg_elist.h"
+#include "eg_io.h"
+#include "eg_lpnum.h"
+#include "eg_macros.h"
+#include "eg_mem.h"
+#include "eg_memslab.h"
+
+#include "eg_lpnum.dbl.h"
+#include "eg_lpnum.mpf.h"
+#include "eg_lpnum.mpq.h"
+
+#include "basicdefs.h"
+#include "urandom.h"
+#include "symtab.h"
+#include "reporter.h"
+#include "bgetopt.h"
+#include "zeit.h"
+#include "logging.h"
+
+#include "QSopt_ex_version.h"
+
+/* Double template headers */
+#include "qstruct_dbl.h"
+#include "editor_dbl.h"
+#include "dstruct_dbl.h"
+#include "factor_dbl.h"
+#include "lpdefs_dbl.h"
+#include "readline_dbl.h"
+#include "lpdata_dbl.h"
+#include "basis_dbl.h"
+#include "dheaps_i_dbl.h"
+#include "qsopt_dbl.h"
+#include "format_dbl.h"
+#include "price_dbl.h"
+#include "priority_dbl.h"
+#include "ratio_dbl.h"
+#include "read_lp_dbl.h"
+#include "read_mps_dbl.h"
+#include "simplex_dbl.h"
+#include "write_lp_dbl.h"
+#include "lib_dbl.h"
+#include "eg_numutil_dbl.h"
+
+/* MPQ template headers */
+#include "qstruct_mpq.h"
+#include "editor_mpq.h"
+#include "dstruct_mpq.h"
+#include "factor_mpq.h"
+#include "lpdefs_mpq.h"
+#include "readline_mpq.h"
+#include "lpdata_mpq.h"
+#include "basis_mpq.h"
+#include "dheaps_i_mpq.h"
+#include "qsopt_mpq.h"
+#include "format_mpq.h"
+#include "price_mpq.h"
+#include "priority_mpq.h"
+#include "ratio_mpq.h"
+#include "read_lp_mpq.h"
+#include "read_mps_mpq.h"
+#include "simplex_mpq.h"
+#include "write_lp_mpq.h"
+#include "lib_mpq.h"
+#include "eg_numutil_mpq.h"
+
+/* MPF template headers */
+#include "qstruct_mpf.h"
+#include "editor_mpf.h"
+#include "dstruct_mpf.h"
+#include "factor_mpf.h"
+#include "lpdefs_mpf.h"
+#include "readline_mpf.h"
+#include "lpdata_mpf.h"
+#include "basis_mpf.h"
+#include "dheaps_i_mpf.h"
+#include "qsopt_mpf.h"
+#include "format_mpf.h"
+#include "price_mpf.h"
+#include "priority_mpf.h"
+#include "ratio_mpf.h"
+#include "read_lp_mpf.h"
+#include "read_mps_mpf.h"
+#include "simplex_mpf.h"
+#include "write_lp_mpf.h"
+#include "lib_mpf.h"
+#include "eg_numutil_mpf.h"
+
+#include "exact.h"
+#include "eg_exutil.h"
+
+#endif /* !QSOPT_EX_H */
diff --git a/qsopt_ex/QSopt_ex_version.c b/qsopt_ex/QSopt_ex_version.c
new file mode 100644
index 0000000..a07bffa
--- /dev/null
+++ b/qsopt_ex/QSopt_ex_version.c
@@ -0,0 +1,33 @@
+/* QSopt_ex_version.c -- QSopt_ex version information
+ * This file is part of QSopt_ex.
+ *
+ * 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
+ *
+ * Copyright (c) 2014-2015 Jon Lund Steffensen <jonlst at gmail.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "logging-private.h"
+
+void
+QSopt_ex_version(void)
+{
+ QSlog("Using %s %s", PACKAGE_NAME, PACKAGE_VERSION);
+}
diff --git a/qsopt_ex/QSopt_ex_version.h b/qsopt_ex/QSopt_ex_version.h
new file mode 100644
index 0000000..12d221a
--- /dev/null
+++ b/qsopt_ex/QSopt_ex_version.h
@@ -0,0 +1,26 @@
+/* QSopt_ex_version.h -- QSopt_ex version information header
+ * This file is part of QSopt_ex.
+ *
+ * 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
+ *
+ * Copyright (c) 2014 Jon Lund Steffensen <jonlst at gmail.com>
+ */
+
+#ifndef QSOPT_EX_VERSION_H
+#define QSOPT_EX_VERSION_H
+
+void QSopt_ex_version(void);
+
+#endif /* !QSOPT_EX_VERSION_H */
diff --git a/qsopt_ex/allocrus.c b/qsopt_ex/allocrus.c
new file mode 100644
index 0000000..17b071a
--- /dev/null
+++ b/qsopt_ex/allocrus.c
@@ -0,0 +1,284 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCSINFO $Id: allocrus.c,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+/****************************************************************************/
+/* */
+/* This file is part of CONCORDE */
+/* */
+/* (c) Copyright 1995--1999 by David Applegate, Robert Bixby, */
+/* Vasek Chvatal, and William Cook */
+/* */
+/* Permission is granted for academic research use. For other uses, */
+/* contact the authors for licensing options. */
+/* */
+/* Use at your own risk. We make no guarantees about the */
+/* correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* MEMORY ALLOCATION MACROS */
+/* */
+/* TSP CODE */
+/* */
+/* */
+/* Written by: Applegate, Bixby, Chvatal, and Cook */
+/* Date: February 2, 1995 (cofeb16) */
+/* */
+/* */
+/* EXPORTED FUNCTIONS: */
+/* */
+/* void *ILLutil_allocrus (size_t size) */
+/* RETURNS a pointer to an allocated block of "size" memory. */
+/* */
+/* void ILLutil_freerus (void *ptr) */
+/* FREES ptr. */
+/* */
+/* void *ILLutil_reallocrus (void *ptr, size_t size) */
+/* REALLOCS ptr to size bytes. */
+/* */
+/* int ILLutil_reallocrus_scale (void **pptr, int *pnnum, int count, */
+/* double scale, size_t size) */
+/* void **pptr (a reference to the pointer to the allocated space) */
+/* int *pnnum (a reference to the number of objects in the */
+/* allocated space) */
+/* int count (a minimum value for the new nnum) */
+/* double scale (a scale factor to apply to nnum) */
+/* int size (the size of objects to be realloced) */
+/* RETURNS 0 if *pptr was successfully changed to point to at */
+/* least max(*pnnum*scale, *pnnum+1000, count) objects. */
+/* *pnnum is changed to the new object count. */
+/* Otherwise, prints an error message, leaves *pptr and */
+/* *pnnum alone, and returns nonzero. */
+/* */
+/* int ILLutil_reallocrus_count (void **pptr, int count, */
+/* size_t size) */
+/* void **pptr (a reference to the pointer to the allocated space) */
+/* int count (number of objects to be realloced) */
+/* int size (the size of the objects to be realloced) */
+/* RETURNS 0 is successful, and 1 if the realloc failed. */
+/* */
+/* ILLbigchunkptr *ILLutil_bigchunkalloc (void) */
+/* RETURNS a ILLbigchunkptr with the "this_one" field loaded with a */
+/* a pointer to a bigchunk of memory. */
+/* NOTES: */
+/* The idea is to use bigchunks (the size of a bigchunk is defined */
+/* by ILL_BIGCHUNK in util.h) to supply local routines with memory */
+/* for ptrs, so the memory can be shared with other */
+/* local routines. */
+/* */
+/* ILLutil_bigchunkfree (ILLbigchunkptr *bp) */
+/* ACTION: Frees a ILLbigchunkptr. */
+/* */
+/* void ILLptrworld_init (ILLptrworld *world) */
+/* initialize a ILLptrworld with 1 reference */
+/* */
+/* void ILLptrworld_add (ILLptrworld *world) */
+/* add a reference to a ILLptrworld */
+/* */
+/* void ILLptrworld_delete (ILLptrworld *world) */
+/* delete a reference to a ptrworld, and free if no more references */
+/* */
+/****************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "logging-private.h"
+
+#include "except.h"
+#include "util.h"
+
+int ILLTRACE_MALLOC = 0;
+
+typedef struct ILLbigchunk
+{
+ char space[ILL_BIGCHUNK];
+ ILLbigchunkptr ptr;
+}
+ILLbigchunk;
+
+void *ILLutil_allocrus (
+ size_t size)
+{
+ void *mem = (void *) NULL;
+
+ if (size == 0)
+ {
+ //QSlog("Warning: 0 bytes allocated");
+ }
+
+ mem = (void *) malloc (size);
+ if (mem == (void *) NULL)
+ {
+ QSlog("Out of memory. Asked for %d bytes", (int) size);
+ }
+ return mem;
+}
+
+void ILLutil_freerus (
+ void *p)
+{
+ if (!p)
+ {
+ //QSlog("Warning: null pointer freed");
+ return;
+ }
+
+ free (p);
+}
+
+void *ILLutil_reallocrus (
+ void *ptr,
+ size_t size)
+{
+ void *newptr;
+
+ if (!ptr)
+ {
+ return ILLutil_allocrus (size);
+ }
+ else
+ {
+ newptr = (void *) realloc (ptr, size);
+ if (!newptr)
+ {
+ QSlog("Out of memory. Tried to grow to %d bytes", (int) size);
+ }
+ return newptr;
+ }
+}
+
+int ILLutil_reallocrus_scale (
+ void **pptr,
+ int *pnnum,
+ int count,
+ double scale,
+ size_t size)
+{
+ int rval = 0;
+ int newsize = (int) (((double) *pnnum) * scale);
+ void *p;
+
+ if (newsize < *pnnum + 1000)
+ newsize = *pnnum + 1000;
+ if (newsize < count)
+ newsize = count;
+ p = ILLutil_reallocrus (*pptr, newsize * size);
+ if (!p)
+ {
+ rval = ILL_GENERAL_ERROR;
+ ILL_REPRT ("ILLutil_reallocrus_scale failed\n");
+ ILL_CLEANUP;
+ }
+ else
+ {
+ *pptr = p;
+ *pnnum = newsize;
+ }
+CLEANUP:
+ return rval;
+}
+
+int ILLutil_reallocrus_count (
+ void **pptr,
+ int count,
+ size_t size)
+{
+ int rval = 0;
+ void *p = ILLutil_reallocrus (*pptr, count * size);
+
+ if (!p)
+ {
+ rval = ILL_GENERAL_ERROR;
+ ILL_REPRT ("ILLutil_reallocrus_count failed\n");
+ ILL_CLEANUP;
+ }
+ else
+ {
+ *pptr = p;
+ }
+CLEANUP:
+ return rval;
+}
+
+
+ILLbigchunkptr *ILLutil_bigchunkalloc (
+ void)
+{
+ ILLbigchunk *p;
+
+ ILL_NEW_no_rval (p, ILLbigchunk);
+
+ p->ptr.this_chunk = p;
+ p->ptr.this_one = (void *) p->space;
+CLEANUP:
+ if (p == (ILLbigchunk *) NULL)
+ {
+ return (ILLbigchunkptr *) NULL;
+ }
+ return &(p->ptr);
+}
+
+void ILLutil_bigchunkfree (
+ ILLbigchunkptr * bp)
+{
+ /* This copy is necessary since ILL_FREE zeros its first argument */
+ ILLbigchunk *p = bp->this_chunk;
+
+ ILL_IFFREE (p, ILLbigchunk);
+}
+
+void ILLptrworld_init (
+ ILLptrworld * world)
+{
+ world->refcount = 1;
+ world->freelist = (void *) NULL;
+ world->chunklist = (ILLbigchunkptr *) NULL;
+}
+
+void ILLptrworld_add (
+ ILLptrworld * world)
+{
+ world->refcount++;
+}
+
+void ILLptrworld_delete (
+ ILLptrworld * world)
+{
+ world->refcount--;
+ if (world->refcount <= 0)
+ {
+ ILLbigchunkptr *bp, *bpnext;
+
+ for (bp = world->chunklist; bp; bp = bpnext)
+ {
+ bpnext = bp->next;
+ ILLutil_bigchunkfree (bp);
+ }
+ world->chunklist = (ILLbigchunkptr *) NULL;
+ world->freelist = (void *) NULL;
+ world->refcount = 0;
+ }
+}
diff --git a/qsopt_ex/allocrus.h b/qsopt_ex/allocrus.h
new file mode 100644
index 0000000..dbe3e07
--- /dev/null
+++ b/qsopt_ex/allocrus.h
@@ -0,0 +1,241 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+#ifndef __ALLOCRUS_H__
+#define __ALLOCRUS_H__
+/****************************************************************************/
+/* */
+/* allocrus.c */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* MEMORY ALLOCATION MACROS */
+/* */
+/* TSP CODE */
+/* */
+/* */
+/* Written by: Applegate, Bixby, Chvatal, and Cook */
+/* Date: February 24, 1995 (cofeb24) */
+/* see allocrus.c */
+/* */
+/****************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "logging-private.h"
+
+extern int ILLTRACE_MALLOC;
+
+#define ILL_UTIL_SAFE_MALLOC(nnum,type,varname) \
+ (((ILLTRACE_MALLOC) ? QSlog("%s.%d: %s: ILL_UTIL_SAFE_MALLOC: %s = %d * %s\n", __FILE__, __LINE__, __DEV_FUNCTION__, #varname, nnum, #type) : 0), \
+ (type *) ILLutil_allocrus (((size_t) (nnum)) * sizeof (type)))
+
+#define ILL_IFFREE(object,type) { \
+ if ((object)) { \
+ ILLutil_freerus ((void *) (object)); \
+ object = (type *) NULL; \
+ }}
+
+#define ILL_PTRWORLD_ALLOC_ROUTINE(type, ptr_alloc_r, ptr_bulkalloc_r) \
+ \
+static int ptr_bulkalloc_r (ILLptrworld *world, int nalloc) \
+{ \
+ ILLbigchunkptr *bp; \
+ int i; \
+ int count = ILL_BIGCHUNK / sizeof ( type ); \
+ type *p; \
+ \
+ while (nalloc > 0) { \
+ bp = ILLutil_bigchunkalloc (); \
+ if (bp == (ILLbigchunkptr *) NULL) { \
+ QSlog("ptr alloc failed\n"); \
+ return 1; \
+ } \
+ bp->next = world->chunklist ; \
+ world->chunklist = bp; \
+ \
+ p = ( type * ) bp->this_one; \
+ for (i=count-2; i>=0; i--) { \
+ p[i].next = &p[i+1]; \
+ } \
+ p[count - 1].next = (type *) world->freelist; \
+ world->freelist = (void *) p; \
+ nalloc -= count; \
+ } \
+ return 0; \
+} \
+ \
+static type *ptr_alloc_r (ILLptrworld *world) \
+{ \
+ type *p; \
+ \
+ if (world->freelist == (void *) NULL) { \
+ if (ptr_bulkalloc_r (world, 1)) { \
+ QSlog("ptr alloc failed\n"); \
+ return ( type * ) NULL; \
+ } \
+ } \
+ p = (type *) world->freelist ; \
+ world->freelist = (void *) p->next; \
+ \
+ return p; \
+}
+
+#define ILL_PTRWORLD_FREE_ROUTINE(type, ptr_free_r) \
+ \
+static void ptr_free_r (ILLptrworld *world, type *p) \
+{ \
+ p->next = (type *) world->freelist ; \
+ world->freelist = (void *) p; \
+}
+
+#define ILL_PTRWORLD_LISTADD_ROUTINE(type, entrytype, ptr_listadd_r, ptr_alloc_r) \
+ \
+static int ptr_listadd_r (type **list, entrytype x, ILLptrworld *world) \
+{ \
+ if (list != (type **) NULL) { \
+ type *p = ptr_alloc_r (world); \
+ \
+ if (p == (type *) NULL) { \
+ QSlog("ptr list add failed\n"); \
+ return 1; \
+ } \
+ p->this = x; \
+ p->next = *list; \
+ *list = p; \
+ } \
+ return 0; \
+}
+
+#define ILL_PTRWORLD_LISTFREE_ROUTINE(type, ptr_listfree_r, ptr_free_r) \
+ \
+static void ptr_listfree_r (ILLptrworld *world, type *p) \
+{ \
+ type *next; \
+ \
+ while (p != (type *) NULL) { \
+ next = p->next; \
+ ptr_free_r (world, p); \
+ p = next; \
+ } \
+}
+
+#define ILL_PTRWORLD_LEAKS_ROUTINE(type, ptr_leaks_r, field, fieldtype) \
+ \
+static int ptr_leaks_r (ILLptrworld *world, int *total, int *onlist) \
+{ \
+ int count = ILL_BIGCHUNK / sizeof ( type ); \
+ int duplicates = 0; \
+ type * p; \
+ ILLbigchunkptr *bp; \
+ \
+ *total = 0; \
+ *onlist = 0; \
+ \
+ for (bp = world->chunklist ; bp; bp = bp->next) \
+ (*total) += count; \
+ \
+ for (p = (type *) world->freelist ; p; p = p->next) { \
+ (*onlist)++; \
+ p-> field = ( fieldtype ) 0; \
+ } \
+ for (p = (type *) world->freelist ; p; p = p->next) { \
+ if ((unsigned long) p-> field == (unsigned long) (size_t) 1) \
+ duplicates++; \
+ else \
+ p-> field = ( fieldtype ) (size_t) 1; \
+ } \
+ if (duplicates) { \
+ QSlog("WARNING: %d duplicates on ptr free list \n", \
+ duplicates); \
+ } \
+ return *total - *onlist; \
+}
+
+#define ILL_PTRWORLD_ROUTINES(type, ptr_alloc_r, ptr_bulkalloc_r, ptr_free_r) \
+ILL_PTRWORLD_ALLOC_ROUTINE (type, ptr_alloc_r, ptr_bulkalloc_r) \
+ILL_PTRWORLD_FREE_ROUTINE (type, ptr_free_r)
+
+#define ILL_PTRWORLD_LIST_ROUTINES(type, entrytype, ptr_alloc_r, ptr_bulkalloc_r, ptr_free_r, ptr_listadd_r, ptr_listfree_r) \
+ILL_PTRWORLD_ROUTINES (type, ptr_alloc_r, ptr_bulkalloc_r, ptr_free_r) \
+ILL_PTRWORLD_LISTADD_ROUTINE (type, entrytype, ptr_listadd_r, ptr_alloc_r) \
+ILL_PTRWORLD_LISTFREE_ROUTINE (type, ptr_listfree_r, ptr_free_r)
+
+#define ILL_BIGCHUNK ((int) ((1<<16) - sizeof (ILLbigchunkptr) - 16))
+
+struct ILLbigchunk;
+
+typedef struct ILLbigchunkptr
+{
+ void *this_one;
+ struct ILLbigchunk *this_chunk;
+ struct ILLbigchunkptr *next;
+}
+ILLbigchunkptr;
+
+
+typedef struct ILLptrworld
+{
+ int refcount;
+ void *freelist;
+ ILLbigchunkptr *chunklist;
+}
+ILLptrworld;
+
+
+
+void *ILLutil_allocrus (
+ size_t size),
+ *ILLutil_reallocrus (
+ void *ptr,
+ size_t size),
+ ILLutil_freerus (
+ void *p),
+ ILLutil_bigchunkfree (
+ ILLbigchunkptr * bp),
+ ILLptrworld_init (
+ ILLptrworld * world),
+ ILLptrworld_add (
+ ILLptrworld * world),
+ ILLptrworld_delete (
+ ILLptrworld * world);
+
+int ILLutil_reallocrus_scale (
+ void **pptr,
+ int *pnnum,
+ int count,
+ double scale,
+ size_t size),
+ ILLutil_reallocrus_count (
+ void **pptr,
+ int count,
+ size_t size);
+
+ILLbigchunkptr *ILLutil_bigchunkalloc (
+ void);
+
+
+
+#endif
diff --git a/qsopt_ex/basicdefs.h b/qsopt_ex/basicdefs.h
new file mode 100644
index 0000000..1b8c01f
--- /dev/null
+++ b/qsopt_ex/basicdefs.h
@@ -0,0 +1,386 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+#ifndef __BASICDEFS__
+#define __BASICDEFS__
+
+/* storage type */
+#define DENSE 0
+#define SPARSE 1
+
+/* type of vector */
+#define ROW_SOLVE 1
+#define COLUMN_SOLVE 2
+
+/* direction of change in non-basic var */
+#define VINCREASE 1
+#define VDECREASE 2
+
+/* status of variables */
+#define STAT_BASIC 1
+#define STAT_UPPER 2
+#define STAT_LOWER 3
+#define STAT_ZERO 4
+
+#define BOUND_LOWER 1
+#define BOUND_UPPER 2
+
+/* type of variables */
+#define VARTIFICIAL 1
+#define VFIXED 2
+#define VFREE 4
+#define VUPPER 8
+#define VLOWER 16
+#define VBOUNDED 32
+
+/* class of variables */
+#define CLASS_STRUCT 0
+#define CLASS_LOGICAL 1
+
+/* algo */
+#define PRIMAL_SIMPLEX 1
+#define DUAL_SIMPLEX 2
+#define PRIMAL_OR_DUAL 3
+
+/* phase */
+#define PRIMAL_PHASEI 1
+#define PRIMAL_PHASEII 2
+#define DUAL_PHASEI 3
+#define DUAL_PHASEII 4
+
+/* number of phases */
+#define PHASEI 1
+#define PHASEII 2
+
+/* type of pricing (all vars or some) */
+#define COMPLETE_PRICING 1
+#define PARTIAL_PRICING 2
+#define MULTI_PART_PRICING 3
+
+/* default pricing */
+
+#define QS_DEFAULT_PRICE_PI QS_PRICE_PSTEEP
+#define QS_DEFAULT_PRICE_PII QS_PRICE_PSTEEP
+#define QS_DEFAULT_PRICE_DI QS_PRICE_DSTEEP
+#define QS_DEFAULT_PRICE_DII QS_PRICE_DSTEEP
+
+/* lp sol status */
+#define ILL_LP_SOLVED 1
+#define ILL_LP_UNSOLVED 2
+#define ILL_MAX_ITER 3
+#define ILL_MAX_TIME 4
+#define ILL_BND_REACHED 5
+#define ILL_PPHASEI_ERROR 6
+#define ILL_PPHASEII_ERROR 7
+#define ILL_DPHASEI_ERROR 8
+#define ILL_DPHASEII_ERROR 9
+#define ILL_LP_ABORTED 10
+
+/* basis status */
+#define OPTIMAL 1
+#define NONOPTIMAL 2
+#define PRIMAL_FEASIBLE 3
+#define PRIMAL_INFEASIBLE 4
+#define PRIMAL_UNBOUNDED 5
+#define DUAL_FEASIBLE 7
+#define DUAL_INFEASIBLE 8
+#define DUAL_UNBOUNDED 9
+
+/* type of ratio test */
+#define RATIOTEST_NORMAL 1
+#define RATIOTEST_HARRIS 2
+
+/* control parameters */
+#define PARAM_PRATIOTESTS 10
+#define PARAM_DRATIOTESTS 20
+#define PARAM_PRIMAL_REFACTORGAP 50
+#define PARAM_PRIMAL_RESOLVEGAP 25
+#define PARAM_DUAL_REFACTORGAP 100
+#define PARAM_DUAL_RESOLVEGAP 25
+#define PARAM_MAX_NOSOLVE 500
+#define PARAM_MAX_NOPROG 300
+#define PARAM_NOPROG_FACTOR 15
+
+/* numerical parameters */
+#define PARAM_BSHIFT 10
+#define PARAM_CSHIFT 10
+
+/* general constants */
+#define PARAM_HEAP_UTRIGGER 10
+#define PARAM_HEAP_RATIO 4.0
+
+/* errors */
+#define E_GENERAL_ERROR 1
+#define E_INV_LINSOLVE_OPTION 2
+#define E_NO_MEMORY 3
+#define E_INVALID_OPTION 4
+#define E_NULL_ARGUMENT 5
+#define E_SIMPLEX_ERROR 6
+#define E_BASIS_SINGULAR 7
+
+#ifndef __QS_BASIS__
+#define __QS_BASIS__
+typedef struct qsbasis
+{
+ int nstruct;
+ int nrows;
+ char *cstat;
+ char *rstat;
+}
+QSbasis;
+#endif
+
+typedef struct itcnt_t
+{
+ int pI_iter;
+ int pII_iter;
+ int dI_iter;
+ int dII_iter;
+ int tot_iter;
+} itcnt_t;
+
+#ifndef QS_DEFINITIONS
+#define QS_DEFINITIONS
+#define QS_MIN (1)
+#define QS_MAX (-1)
+
+/****************************************************************************/
+/* */
+/* PARAMETERS THAT CAN BE SET BY setparam */
+/* */
+/****************************************************************************/
+
+
+#define QS_PARAM_PRIMAL_PRICING 0
+#define QS_PARAM_DUAL_PRICING 2
+#define QS_PARAM_SIMPLEX_DISPLAY 4
+#define QS_PARAM_SIMPLEX_MAX_ITERATIONS 5
+#define QS_PARAM_SIMPLEX_MAX_TIME 6
+#define QS_PARAM_SIMPLEX_SCALING 7
+#define QS_PARAM_OBJULIM 8
+#define QS_PARAM_OBJLLIM 9
+
+
+/****************************************************************************/
+/* */
+/* VALUES FOR PRICING PARAMETERS */
+/* */
+/****************************************************************************/
+
+#define QS_PRICE_PDANTZIG 1
+#define QS_PRICE_PDEVEX 2
+#define QS_PRICE_PSTEEP 3
+#define QS_PRICE_PMULTPARTIAL 4
+
+#define QS_PRICE_DDANTZIG 6
+#define QS_PRICE_DSTEEP 7
+#define QS_PRICE_DMULTPARTIAL 8
+#define QS_PRICE_DDEVEX 9
+
+
+/****************************************************************************/
+/* */
+/* VALUES FOR BASIS STATUS */
+/* */
+/****************************************************************************/
+
+
+#define QS_COL_BSTAT_LOWER '0'
+#define QS_COL_BSTAT_BASIC '1'
+#define QS_COL_BSTAT_UPPER '2'
+#define QS_COL_BSTAT_FREE '3'
+
+#define QS_ROW_BSTAT_LOWER '0'
+#define QS_ROW_BSTAT_BASIC '1'
+#define QS_ROW_BSTAT_UPPER '2'
+
+
+/****************************************************************************/
+/* */
+/* Return Status for dbl_QSopt_primal, dbl_QSopt_dual, dbl_QSget_status */
+/* */
+/****************************************************************************/
+
+#define QS_LP_OPTIMAL 1
+#define QS_LP_INFEASIBLE 2
+#define QS_LP_UNBOUNDED 3
+#define QS_LP_ITER_LIMIT 4
+#define QS_LP_TIME_LIMIT 5
+#define QS_LP_UNSOLVED 6
+#define QS_LP_ABORTED 7
+#define QS_LP_NUMERR 8
+#define QS_LP_OBJ_LIMIT 9
+#define QS_LP_MODIFIED 100
+#define QS_LP_CHANGE_PREC 1024
+#endif
+
+
+
+/** @brief If set to one, them we allow to re-start the simplex algorithm due to
+ * numerical issues */
+#define DO_NUMER 0
+/** @brief If set to one, then we allow to re-start simplex due to singular
+ * basis */
+#define DO_SINGULAR 0
+
+/** @brief Factor for wich we change tolerances each time we have to resume
+ * simplex */
+#define SIMPLEX_FACTOR 5U
+#define DENSE_PI 0
+#define DENSE_PIIPI 0
+#define DENSE_NORM 0
+#define SIMPLEX_DEBUG 0
+
+
+/* possible values of nextstep */
+#define SIMPLEX_CONTINUE 1
+#define SIMPLEX_TERMINATE 2
+#define SIMPLEX_RESUME 3
+
+/* reason for resuming simplex */
+#define SIMPLEX_RESUME_SING 1
+#define SIMPLEX_RESUME_UNSHIFT 2
+#define SIMPLEX_RESUME_NUMER 3
+
+/* values for newphase */
+#define SIMPLEX_PHASE_RECOMP 1
+#define SIMPLEX_PHASE_NEW 2
+
+#define SIMPLEX_PIVOTINROW 1
+#define SIMPLEX_PIVOTINCOL 2
+#define SIMPLEX_MAX_RESTART 4
+#define SIMPLEX_MAX_PIVOT_FAIL 300
+
+
+#define FALSE 0
+#define TRUE 1
+#define QS_FACTOR_MAX_K 1
+#define QS_FACTOR_P 2
+#define QS_FACTOR_ETAMAX 3
+#define QS_FACTOR_FZERO_TOL 4
+#define QS_FACTOR_SZERO_TOL 5
+#define QS_FACTOR_PARTIAL_TOL 6
+#define QS_FACTOR_UR_SPACE_MUL 7
+#define QS_FACTOR_UC_SPACE_MUL 8
+#define QS_FACTOR_LC_SPACE_MUL 9
+#define QS_FACTOR_LR_SPACE_MUL 10
+#define QS_FACTOR_ER_SPACE_MUL 11
+#define QS_FACTOR_GROW_MUL 12
+#define QS_FACTOR_MAXMULT 13
+#define QS_FACTOR_MINMULT 14
+#define QS_FACTOR_UPDMAXMULT 15
+#define QS_FACTOR_DENSE_FRACT 16
+#define QS_FACTOR_DENSE_MIN 17
+#define E_CHECK_FAILED 6
+#define E_NO_PIVOT 7
+#define E_FACTOR_BLOWUP 8
+#define E_UPDATE_NOSPACE 9
+#define E_UPDATE_SINGULAR_ROW 10
+#define E_UPDATE_SINGULAR_COL 11
+#define E_SING_NO_DATA 12
+#define E_SINGULAR_INTERNAL 13
+#define SPARSE_FACTOR 0.05
+#define CNT_YNZ 1 /* nz in entering columns */
+#define CNT_ZNZ 2 /* nz in ith row of B^{-1}, ie z_i */
+#define CNT_ZANZ 3 /* nz in ith row of B^{-1}, ie z_i */
+#define CNT_PINZ 4 /* nz in phase II pi (solve) */
+#define CNT_P1PINZ 5 /* nz in phase I pi (solve) */
+#define CNT_UPNZ 6 /* nz in ftran_updates */
+#define CNT_PPHASE1ITER 7 /* primal phase I iterations */
+#define CNT_PPHASE2ITER 8
+#define CNT_DPHASE1ITER 9 /* dual phase I iterations */
+#define CNT_DPHASE2ITER 10
+#define CNT_PIPIV 11
+#define CNT_PIIPIV 12
+#define CNT_DIPIV 13
+#define CNT_DIIPIV 14
+#define CNT_YRAVG 15
+#define CNT_ZARAVG 16
+
+#define ROW_PIVOT 0
+#define COL_PIVOT 1
+
+#define ILL_LP_OPTIMAL 1
+#define ILL_LP_NONOPTIMAL 2
+#define ILL_LP_PRIMAL_FEASIBLE 3
+#define ILL_LP_PRIMAL_INFEASIBLE 4
+#define ILL_LP_PRIMAL_UNBOUNDED 5
+#define ILL_LP_DUAL_FEASIBLE 6
+#define ILL_LP_DUAL_INFEASIBLE 7
+#define ILL_LP_DUAL_UNBOUNDED 8
+
+typedef enum
+{ ILL_MPS_NAME, ILL_MPS_OBJSENSE, ILL_MPS_OBJNAME,
+ ILL_MPS_ROWS, ILL_MPS_COLS, ILL_MPS_RHS, ILL_MPS_RANGES,
+ ILL_MPS_BOUNDS, ILL_MPS_REFROW, ILL_MPS_ENDATA,
+ ILL_MPS_NONE
+}
+ILLmps_section;
+
+#define ILL_MPS_N_SECTIONS ILL_MPS_NONE
+
+/*define as > 0 if heap is to be used */
+#define USEHEAP 1
+
+/*result of pricing */
+#define PRICE_OPTIMAL 1
+#define PRICE_NONOPTIMAL 2
+
+/*type of pricing */
+#define ROW_PRICING 1
+#define COL_PRICING 2
+
+
+/****************************************************************************
+ * error collection
+ */
+#define QS_DATA_ERROR 0
+#define QS_DATA_WARN 1
+#define QS_MPS_FORMAT_ERROR 2
+#define QS_MPS_FORMAT_WARN 3
+#define QS_LP_FORMAT_ERROR 4
+#define QS_LP_FORMAT_WARN 5
+#define QS_INPUT_NERROR 8
+
+/* defs for phase I ratio test */
+#define BBOUND 1
+#define BATOLOWER 2
+#define BATOUPPER 3
+#define BBTOLOWER 4
+#define BBTOUPPER 5
+#define BSKIP 6
+
+/* result of ratio test */
+#define RATIO_UNBOUNDED 1
+#define RATIO_NOBCHANGE 2
+#define RATIO_BCHANGE 3
+#define RATIO_FAILED 4
+#define RATIO_NEGATIVE 5
+
+/* warning level */
+#define QSE_WLVL 10000
+
+
+
+
+
+
+#endif
diff --git a/qsopt_ex/basis.c b/qsopt_ex/basis.c
new file mode 100644
index 0000000..576c920
--- /dev/null
+++ b/qsopt_ex/basis.c
@@ -0,0 +1,1554 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: basis.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+static int TRACE = 0;
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "eg_lpnum.h"
+#include "eg_io.h"
+#include "except.h"
+#include "util.h"
+
+#include "sortrus_EGLPNUM_TYPENAME.h"
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+#include "qstruct_EGLPNUM_TYPENAME.h"
+#include "qsopt_EGLPNUM_TYPENAME.h"
+#include "basis_EGLPNUM_TYPENAME.h"
+#include "fct_EGLPNUM_TYPENAME.h"
+#include "lp_EGLPNUM_TYPENAME.h"
+#include "lib_EGLPNUM_TYPENAME.h"
+
+//#define DJZERO_TOLER EGLPNUM_TYPENAME_PFEAS_TOLER
+#define BASIS_STATS 0
+//#define BASIS_DEBUG 10
+#define BASIS_DEBUG 0
+
+void EGLPNUM_TYPENAME_ILLbasis_init_vardata (
+ EGLPNUM_TYPENAME_var_data * vd)
+{
+ memset (vd, 0, sizeof (EGLPNUM_TYPENAME_var_data));
+ EGLPNUM_TYPENAME_EGlpNumInitVar (vd->cmax);
+}
+
+void EGLPNUM_TYPENAME_ILLbasis_clear_vardata (
+ EGLPNUM_TYPENAME_var_data * vd)
+{
+ EGLPNUM_TYPENAME_EGlpNumClearVar (vd->cmax);
+ memset (vd, 0, sizeof (EGLPNUM_TYPENAME_var_data));
+}
+
+static void get_var_info (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_var_data * v);
+
+static int init_slack_basis (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int *vstat,
+ int *irow,
+ int *rrow,
+ int *unitcol,
+ int *icol,
+ int *rcol),
+ get_initial_basis1 (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int *vstat),
+ get_initial_basis2 (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int *vstat),
+ set_basis_indices (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int *vstat),
+ choose_basis (
+ int algorithm,
+ EGLPNUM_TYPE pinf1,
+ EGLPNUM_TYPE dinf1,
+ EGLPNUM_TYPE pinf2,
+ EGLPNUM_TYPE dinf2);
+
+void EGLPNUM_TYPENAME_ILLbasis_init_basisinfo (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ lp->baz = 0;
+ lp->nbaz = 0;
+ lp->vstat = 0;
+ lp->vindex = 0;
+ lp->f = 0;
+}
+
+void EGLPNUM_TYPENAME_ILLbasis_free_basisinfo (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ ILL_IFFREE (lp->baz, int);
+ ILL_IFFREE (lp->nbaz, int);
+ ILL_IFFREE (lp->vstat, int);
+ ILL_IFFREE (lp->vindex, int);
+
+ if (lp->f)
+ {
+ EGLPNUM_TYPENAME_ILLfactor_free_factor_work (lp->f);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (lp->f->fzero_tol);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (lp->f->szero_tol);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (lp->f->partial_tol);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (lp->f->maxelem_orig);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (lp->f->maxelem_factor);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (lp->f->maxelem_cur);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (lp->f->partial_cur);
+ ILL_IFFREE (lp->f, EGLPNUM_TYPENAME_factor_work);
+ }
+}
+
+int EGLPNUM_TYPENAME_ILLbasis_build_basisinfo (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ int rval = 0;
+
+ ILL_SAFE_MALLOC (lp->baz, lp->O->nrows, int);
+ ILL_SAFE_MALLOC (lp->nbaz, lp->O->ncols, int);
+ ILL_SAFE_MALLOC (lp->vstat, lp->O->ncols, int);
+ ILL_SAFE_MALLOC (lp->vindex, lp->O->ncols, int);
+
+ lp->fbasisid = -1;
+
+CLEANUP:
+ if (rval)
+ EGLPNUM_TYPENAME_ILLbasis_free_basisinfo (lp);
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLbasis_load (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_ILLlp_basis * B)
+{
+ int rval = 0;
+ char *cstat = B->cstat;
+ char *rstat = B->rstat;
+ int *structmap = lp->O->structmap;
+ int *rowmap = lp->O->rowmap;
+ char *sense = lp->O->sense;
+ int i, j, ncols = lp->O->ncols, nrows = lp->O->nrows, nstruct = lp->O->nstruct;
+ int basic = 0, nonbasic = 0;
+
+ EGLPNUM_TYPENAME_ILLbasis_free_basisinfo (lp);
+ EGLPNUM_TYPENAME_ILLbasis_init_basisinfo (lp);
+ rval = EGLPNUM_TYPENAME_ILLbasis_build_basisinfo (lp);
+ CHECKRVALG (rval, CLEANUP);
+
+ for (i = 0; i < nstruct; i++)
+ {
+ j = structmap[i];
+ if (cstat[i] == QS_COL_BSTAT_BASIC)
+ {
+ lp->vstat[j] = STAT_BASIC;
+ lp->baz[basic] = j;
+ lp->vindex[j] = basic;
+ basic++;
+ }
+ else
+ {
+ lp->nbaz[nonbasic] = j;
+ lp->vindex[j] = nonbasic;
+ nonbasic++;
+ switch (cstat[i])
+ {
+ case QS_COL_BSTAT_LOWER:
+ lp->vstat[j] = STAT_LOWER;
+ break;
+ case QS_COL_BSTAT_UPPER:
+ lp->vstat[j] = STAT_UPPER;
+ break;
+ case QS_COL_BSTAT_FREE:
+ lp->vstat[j] = STAT_ZERO;
+ break;
+ default:
+ QSlog("unknown col basis stat 1: %c", cstat[i]);
+ rval = 1;
+ goto CLEANUP;
+ }
+ }
+ }
+
+ for (i = 0; i < nrows; i++)
+ {
+ j = rowmap[i];
+ if (sense[i] == 'R')
+ {
+ if (rstat[i] == QS_ROW_BSTAT_BASIC)
+ {
+ lp->vstat[j] = STAT_BASIC;
+ lp->baz[basic] = j;
+ lp->vindex[j] = basic;
+ basic++;
+ }
+ else
+ {
+ lp->nbaz[nonbasic] = j;
+ lp->vindex[j] = nonbasic;
+ nonbasic++;
+ switch (rstat[i])
+ {
+ case QS_ROW_BSTAT_LOWER:
+ lp->vstat[j] = STAT_LOWER;
+ break;
+ case QS_ROW_BSTAT_UPPER:
+ lp->vstat[j] = STAT_UPPER;
+ break;
+ default:
+ QSlog("unknown range basis stat 2");
+ rval = 1;
+ goto CLEANUP;
+ }
+ }
+ }
+ else
+ {
+ switch (rstat[i])
+ {
+ case QS_ROW_BSTAT_BASIC:
+ lp->vstat[j] = STAT_BASIC;
+ lp->baz[basic] = j;
+ lp->vindex[j] = basic;
+ basic++;
+ break;
+ case QS_ROW_BSTAT_LOWER:
+ lp->vstat[j] = STAT_LOWER;
+ lp->nbaz[nonbasic] = j;
+ lp->vindex[j] = nonbasic;
+ nonbasic++;
+ break;
+ default:
+ QSlog("unknown row basis stat 3");
+ rval = 1;
+ goto CLEANUP;
+ }
+ }
+ }
+
+ if (basic + nonbasic != ncols)
+ {
+ QSlog("error in counts in ILLopt_load_basis");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ if (lp->fbasisid != 0)
+ lp->basisid = 0;
+ else
+ lp->basisid = 1;
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLbasis_tableau_row (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int row,
+ EGLPNUM_TYPE * brow,
+ EGLPNUM_TYPE * trow,
+ EGLPNUM_TYPE * rhs,
+ int strict)
+{
+ int rval = 0;
+ int i;
+ int singular = 0;
+ int indx;
+ EGLPNUM_TYPE coef;
+ EGLPNUM_TYPE sum;
+ EGLPNUM_TYPENAME_svector z, zA;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (coef);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (sum);
+ EGLPNUM_TYPENAME_EGlpNumZero (sum);
+
+ EGLPNUM_TYPENAME_ILLsvector_init (&z);
+ EGLPNUM_TYPENAME_ILLsvector_init (&zA);
+
+ if (lp->basisid == -1)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLbasis_tableau_row: no basis");
+ rval = E_GENERAL_ERROR;
+ ILL_CLEANUP;
+ }
+ if (lp->fbasisid != lp->basisid)
+ { /* Needs to be changed */
+ rval = EGLPNUM_TYPENAME_ILLbasis_factor (lp, &singular);
+ CHECKRVALG (rval, CLEANUP);
+ if (singular)
+ {
+ MESSAGE (__QS_SB_VERB, "Singular Basis found!");
+ rval = E_BASIS_SINGULAR;
+ ILL_CLEANUP;
+ }
+ }
+ if (brow == NULL)
+ {
+ QSlog("No array for basis inverse row");
+ rval = E_GENERAL_ERROR;
+ ILL_CLEANUP;
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&z, lp->nrows);
+ CHECKRVALG (rval, CLEANUP);
+ EGLPNUM_TYPENAME_ILLfct_compute_zz (lp, &z, row);
+
+ for (i = 0; i < lp->O->nrows; i++)
+ EGLPNUM_TYPENAME_EGlpNumZero (brow[i]);
+ for (i = 0; i < z.nzcnt; i++)
+ {
+ indx = z.indx[i];
+ EGLPNUM_TYPENAME_EGlpNumCopy (coef, z.coef[i]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (brow[indx], coef);
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, coef, lp->bz[indx]);
+ }
+
+ if (rhs != NULL)
+ EGLPNUM_TYPENAME_EGlpNumCopy (*rhs, sum);
+ if (trow != NULL)
+ {
+ if (!strict)
+ {
+ rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&zA, lp->ncols);
+ if (rval)
+ ILL_CLEANUP;
+ ILL_IFTRACE ("%s:\n", __func__);
+ rval = EGLPNUM_TYPENAME_ILLfct_compute_zA (lp, &z, &zA);
+ CHECKRVALG (rval, CLEANUP);
+
+ for (i = 0; i < lp->ncols; i++)
+ EGLPNUM_TYPENAME_EGlpNumZero (trow[i]);
+ for (i = 0; i < zA.nzcnt; i++)
+ EGLPNUM_TYPENAME_EGlpNumCopy (trow[lp->nbaz[zA.indx[i]]], zA.coef[i]);
+ EGLPNUM_TYPENAME_EGlpNumOne (trow[lp->baz[row]]);
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_ILLfct_compute_vA (lp, &z, trow);
+ }
+ }
+
+#if BASIS_DEBUG > 0
+ if (rhs != NULL && trow != NULL)
+ {
+ EGLPNUM_TYPE *tr = NULL;
+
+ EGLPNUM_TYPENAME_EGlpNumZero (sum);
+ if (strict)
+ tr = trow;
+ else
+ {
+ tr = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->ncols);
+ EGLPNUM_TYPENAME_ILLfct_compute_vA (lp, &z, tr);
+ }
+ for (i = 0; i < lp->nrows; i++)
+ if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (tr[lp->baz[i]]))
+ EGLPNUM_TYPENAME_EGlpNumAddTo (sum, tr[lp->baz[i]]);
+ else
+ EGLPNUM_TYPENAME_EGlpNumSubTo (sum, tr[lp->baz[i]]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (coef, EGLPNUM_TYPENAME_oneLpNum);
+ EGLPNUM_TYPENAME_EGlpNumSubTo (coef, sum);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (coef))
+ EGLPNUM_TYPENAME_EGlpNumSign (coef);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_PIVZ_TOLER, coef))
+ QSlog("tableau: bas computed = %.12f", EGLPNUM_TYPENAME_EGlpNumToLf (sum));
+ if (!strict)
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (tr);
+#if BASIS_DEBUG > 1
+ EGLPNUM_TYPENAME_EGlpNumZero (sum);
+ for (i = 0; i < lp->ncols; i++)
+ {
+ if (lp->vstat[i] == STAT_BASIC)
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, lp->xbz[lp->vindex[i]], trow[i]);
+ else if (lp->vstat[i] == STAT_UPPER)
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, lp->uz[i], trow[i]);
+ else if (lp->vstat[i] == STAT_LOWER)
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, lp->lz[i], trow[i]);
+ }
+ EGLPNUM_TYPENAME_EGlpNumSet (coef, 1e-10);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeq (sum, *rhs, coef))
+ QSlog("tableau rhs = %.9f, computed = %.9f",
+ EGLPNUM_TYPENAME_EGlpNumToLf (*rhs), EGLPNUM_TYPENAME_EGlpNumToLf (sum));
+#endif
+ }
+#endif
+
+CLEANUP:
+ EGLPNUM_TYPENAME_ILLsvector_free (&z);
+ EGLPNUM_TYPENAME_ILLsvector_free (&zA);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (coef);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (sum);
+ return rval;
+}
+
+static void get_var_info (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_var_data * v)
+{
+ int i = 0;
+
+ v->nartif = 0;
+ v->nslacks = 0;
+ v->nfree = 0;
+ v->nbndone = 0;
+ v->nbounded = 0;
+ v->nfixed = 0;
+ EGLPNUM_TYPENAME_EGlpNumCopy (v->cmax, EGLPNUM_TYPENAME_NINFTY);
+
+ for (i = 0; i < lp->ncols; i++)
+ {
+ switch (lp->vtype[i])
+ {
+ case VARTIFICIAL:
+ v->nartif++;
+ break;
+ case VFREE:
+ v->nfree++;
+ break;
+ case VLOWER:
+ case VUPPER:
+ if (lp->vclass[i] == CLASS_LOGICAL)
+ v->nslacks++;
+ else
+ v->nbndone++;
+ break;
+
+ case VFIXED:
+ v->nfixed++;
+ case VBOUNDED:
+ if (lp->vclass[i] == CLASS_LOGICAL)
+ v->nslacks++;
+ else
+ v->nbounded++;
+ break;
+ }
+ EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (v->cmax, lp->cz[i]);
+ }
+
+#if BASIS_STATS > 0
+ QSlog("cols = %d, acols = %d, total = %d, nrows = %d, nlog = %d",
+ lp->ncols, lp->ncols - lp->nrows,
+ v->nartif + v->nfree + v->nslacks + v->nbndone + v->nbounded,
+ lp->nrows, v->nartif + v->nslacks);
+#endif
+}
+
+static int init_slack_basis (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int *vstat,
+ int *irow,
+ int *rrow,
+ int *unitcol,
+ int *icol,
+ int *rcol)
+{
+ int j, r, vt;
+ int nslacks = 0;
+
+ for (j = 0; j < lp->ncols; j++)
+ {
+ r = lp->matind[lp->matbeg[j]];
+ vt = lp->vtype[j];
+
+ if ((vt == VUPPER || vt == VLOWER || vt == VBOUNDED || vt == VFIXED) &&
+ lp->vclass[j] == CLASS_LOGICAL)
+ {
+
+ vstat[j] = STAT_BASIC;
+ irow[r] = 1;
+ rrow[r] = 1;
+ unitcol[r] = j;
+ if (icol != NULL)
+ {
+ icol[j] = 1;
+ rcol[j] = 1;
+ }
+ nslacks++;
+ }
+ else if (vt == VARTIFICIAL)
+ {
+ unitcol[r] = j;
+ vstat[j] = STAT_UPPER;
+ }
+ else if (vt == VFREE)
+ vstat[j] = STAT_ZERO;
+ else if (vt == VFIXED || vt == VUPPER)
+ vstat[j] = STAT_UPPER;
+ else if (vt == VLOWER)
+ vstat[j] = STAT_LOWER;
+ else if (vt == VBOUNDED)
+ {
+ if (fabs (EGLPNUM_TYPENAME_EGlpNumToLf (lp->lz[j])) < fabs (EGLPNUM_TYPENAME_EGlpNumToLf (lp->uz[j])))
+ vstat[j] = STAT_LOWER;
+ else
+ vstat[j] = STAT_UPPER;
+ }
+ }
+ return nslacks;
+}
+
+static int primal_col_select (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int *vstat,
+ int *irow,
+ int *rrow,
+ int *unitcol,
+ EGLPNUM_TYPE * v,
+ int *perm,
+ int *porder,
+ int nbelem,
+ int pcols)
+{
+ int i, j, k, tr, r = 0;
+ int mcnt, mbeg;
+ int *matbeg = lp->matbeg;
+ int *matcnt = lp->matcnt;
+ int *matind = lp->matind;
+ EGLPNUM_TYPE *matval = lp->matval;
+ EGLPNUM_TYPE alpha, val, maxelem;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (alpha);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (val);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (maxelem);
+
+ for (k = 0; k < pcols; k++)
+ {
+ j = porder[perm[k]];
+ mcnt = matcnt[j];
+ mbeg = matbeg[j];
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (alpha, EGLPNUM_TYPENAME_NINFTY);
+ EGLPNUM_TYPENAME_EGlpNumCopy (maxelem, EGLPNUM_TYPENAME_NINFTY);
+
+ for (i = 0; i < mcnt; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs (val, matval[mbeg + i]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (maxelem, val))
+ EGLPNUM_TYPENAME_EGlpNumCopy (maxelem, val);
+ if (rrow[matind[mbeg + i]] == 0 && EGLPNUM_TYPENAME_EGlpNumIsLess (alpha, val))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (alpha, val);
+ r = matind[mbeg + i];
+ }
+ }
+ EGLPNUM_TYPENAME_EGlpNumCopy (val, maxelem);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (val, EGLPNUM_TYPENAME_PARAM_IBASIS_RPIVOT);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (val, alpha))
+ {
+ vstat[j] = STAT_BASIC;
+ nbelem++;
+ irow[r] = 1;
+ EGLPNUM_TYPENAME_EGlpNumCopy (v[r], alpha);
+ for (i = 0; i < mcnt; i++)
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (matval[mbeg + i]))
+ rrow[matind[mbeg + i]]++;
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (alpha, EGLPNUM_TYPENAME_NINFTY);
+ for (i = 0; i < mcnt; i++)
+ {
+ tr = matind[mbeg + i];
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs (val, matval[mbeg + i]);
+ EGLPNUM_TYPENAME_EGlpNumDivTo (val, EGLPNUM_TYPENAME_PARAM_IBASIS_RTRIANG);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (v[tr], EGLPNUM_TYPENAME_INFTY) && EGLPNUM_TYPENAME_EGlpNumIsLess (v[tr], val))
+ {
+ EGLPNUM_TYPENAME_EGlpNumZero (alpha);
+ break;
+ }
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs (val, matval[mbeg + i]);
+ if (irow[tr] == 0 && EGLPNUM_TYPENAME_EGlpNumIsLess (alpha, val))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (alpha, val);
+ r = tr;
+ }
+ }
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (alpha) && EGLPNUM_TYPENAME_EGlpNumIsNeqq (alpha, EGLPNUM_TYPENAME_NINFTY))
+ {
+ vstat[j] = STAT_BASIC;
+ nbelem++;
+ irow[r] = 1;
+ EGLPNUM_TYPENAME_EGlpNumCopy (v[r], alpha);
+ for (i = 0; i < mcnt; i++)
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (matval[mbeg + i]))
+ rrow[matind[mbeg + i]]++;
+ }
+ }
+ }
+#if BASIS_STATS > 0
+ QSlog("nartifs = %d", lp->nrows - nbelem);
+#endif
+
+ if (nbelem < lp->nrows)
+ {
+ for (i = 0; i < lp->nrows; i++)
+ {
+ if (irow[i] == 0)
+ {
+ if (unitcol[i] != -1)
+ {
+ vstat[unitcol[i]] = STAT_BASIC;
+ nbelem++;
+ }
+ else
+ {
+ QSlog("Error: Not enough artificials");
+ return -1;
+ }
+ }
+ }
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (alpha);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (val);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (maxelem);
+ return nbelem;
+}
+
+/* This is an implementation of the initial basis procedure
+ in: "Implementing the simplex method: the initial basis", by
+ Bob Bixby.
+ Goals: choose initial variables to go into basis which satisfy:
+ 1) vars are slacks, 2) vars have freedom to move
+ 3) initial submatrix is nonsingular, 4) low objective function
+ contribution.
+*/
+static int get_initial_basis1 (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int *vstat)
+{
+ int rval = 0;
+ int i, j, tot1 = 0, tot2 = 0;
+ int nbelem = 0, nslacks = 0;
+ int tfree = 0, tbndone = 0;
+ int tbounded = 0;
+ int *irow = NULL, *rrow = NULL;
+ int *perm = NULL, *porder = NULL;
+ int *unitcol = NULL;
+ EGLPNUM_TYPE cmax;
+ EGLPNUM_TYPE *v = NULL;
+ EGLPNUM_TYPE *qpenalty = NULL;
+ EGLPNUM_TYPENAME_var_data vd;
+
+ EGLPNUM_TYPENAME_ILLbasis_init_vardata (&vd);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (cmax);
+
+ get_var_info (lp, &vd);
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (vd.cmax))
+ EGLPNUM_TYPENAME_EGlpNumOne (cmax);
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (cmax, vd.cmax);
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (cmax, 1000);
+ }
+
+ ILL_SAFE_MALLOC (irow, lp->nrows, int);
+ ILL_SAFE_MALLOC (rrow, lp->nrows, int);
+
+ v = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+ ILL_SAFE_MALLOC (unitcol, lp->nrows, int);
+
+ for (i = 0; i < lp->nrows; i++)
+ {
+ unitcol[i] = -1;
+ EGLPNUM_TYPENAME_EGlpNumCopy (v[i], EGLPNUM_TYPENAME_INFTY);
+ irow[i] = 0;
+ rrow[i] = 0;
+ }
+
+ nslacks = init_slack_basis (lp, vstat, irow, rrow, unitcol, NULL, NULL);
+ if (nslacks != vd.nslacks)
+ {
+ QSlog("complain: incorrect basis info(slacks)");
+ rval = E_SIMPLEX_ERROR;
+ ILL_CLEANUP;
+ }
+ if (nslacks == lp->nrows)
+ ILL_CLEANUP;
+ nbelem = nslacks;
+ if (nbelem < lp->nrows)
+ {
+ for (i = 0; i < lp->nrows; i++)
+ {
+ if (irow[i] == 0)
+ {
+ if (unitcol[i] != -1)
+ {
+ vstat[unitcol[i]] = STAT_BASIC;
+ nbelem++;
+ }
+ else
+ {
+ QSlog("Error: Not enough artificials");
+ return -1;
+ }
+ }
+ }
+ }
+ ILL_CLEANUP;
+
+ tot1 = vd.nfree + vd.nbndone;
+ tot2 = vd.nfree + vd.nbndone + vd.nbounded;
+ ILL_SAFE_MALLOC (perm, tot2, int);
+ ILL_SAFE_MALLOC (porder, tot2, int);
+
+ qpenalty = EGLPNUM_TYPENAME_EGlpNumAllocArray (tot2);
+
+ for (j = 0; j < lp->ncols; j++)
+ {
+ if (vstat[j] == STAT_BASIC)
+ continue;
+
+ switch (lp->vtype[j])
+ {
+ case VFREE:
+ porder[tfree] = j;
+ perm[tfree] = tfree;
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (qpenalty[tfree], lp->cz[j], cmax);
+ tfree++;
+ break;
+
+ case VLOWER:
+ case VUPPER:
+ porder[vd.nfree + tbndone] = j;
+ perm[vd.nfree + tbndone] = tbndone;
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (qpenalty[vd.nfree + tbndone], lp->cz[j], cmax);
+ if (lp->vtype[j] == VLOWER)
+ EGLPNUM_TYPENAME_EGlpNumAddTo (qpenalty[vd.nfree + tbndone], lp->lz[j]);
+ else
+ EGLPNUM_TYPENAME_EGlpNumSubTo (qpenalty[vd.nfree + tbndone], lp->uz[j]);
+ tbndone++;
+ break;
+
+ case VFIXED:
+ case VBOUNDED:
+ porder[tot1 + tbounded] = j;
+ perm[tot1 + tbounded] = tbounded;
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (qpenalty[tot1 + tbndone], lp->cz[j], cmax);
+ EGLPNUM_TYPENAME_EGlpNumAddTo (qpenalty[tot1 + tbndone], lp->lz[j]);
+ EGLPNUM_TYPENAME_EGlpNumSubTo (qpenalty[tot1 + tbndone], lp->uz[j]);
+ tbounded++;
+ break;
+ }
+ }
+ if (tfree != vd.nfree || tbndone != vd.nbndone || tbounded != vd.nbounded)
+ {
+ QSlog("complain: incorrect basis info");
+ rval = E_SIMPLEX_ERROR;
+ ILL_CLEANUP;
+ }
+
+ EGLPNUM_TYPENAME_ILLutil_EGlpNum_perm_quicksort (perm, qpenalty, vd.nfree);
+ EGLPNUM_TYPENAME_ILLutil_EGlpNum_perm_quicksort (perm + vd.nfree, qpenalty + vd.nfree,
+ vd.nbndone);
+ EGLPNUM_TYPENAME_ILLutil_EGlpNum_perm_quicksort (perm + tot1, qpenalty + tot1, vd.nbounded);
+
+ for (i = 0; i < vd.nbndone; i++)
+ perm[vd.nfree + i] += vd.nfree;
+ for (i = 0; i < vd.nbounded; i++)
+ perm[tot1 + i] += tot1;
+
+ nbelem =
+ primal_col_select (lp, vstat, irow, rrow, unitcol, v, perm, porder, nbelem,
+ tot2);
+ if (nbelem != lp->nrows)
+ {
+ QSlog("complain: incorrect final basis size");
+ rval = E_SIMPLEX_ERROR;
+ ILL_CLEANUP;
+ }
+
+CLEANUP:
+ EGLPNUM_TYPENAME_EGlpNumClearVar (cmax);
+ if (rval)
+ EGLPNUM_TYPENAME_ILLbasis_free_basisinfo (lp);
+ ILL_IFFREE (irow, int);
+ ILL_IFFREE (rrow, int);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (v);
+ ILL_IFFREE (perm, int);
+ ILL_IFFREE (porder, int);
+ ILL_IFFREE (unitcol, int);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (qpenalty);
+ EGLPNUM_TYPENAME_ILLbasis_clear_vardata (&vd);
+ EG_RETURN (rval);
+}
+
+static int get_initial_basis2 (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int *vstat)
+{
+ int rval = 0;
+ int i, j, k, tot1, tot2;
+ int rbeg, rcnt, mcnt;
+ int nbelem = 0, nslacks = 0;
+ int tfree = 0, tbndone = 0;
+ int tbounded = 0;
+ int *irow = NULL, *rrow = NULL;
+ int *perm = NULL, *porder = NULL;
+ int *unitcol = NULL;
+ EGLPNUM_TYPE *v = NULL;
+ EGLPNUM_TYPE *qpenalty = NULL;
+ int col = 0, s_i = 0, selc = 0;
+ int *icol = NULL, *rcol = NULL;
+ int *plen = NULL;
+ EGLPNUM_TYPE *dj = NULL;
+ EGLPNUM_TYPENAME_var_data vd;
+ EGLPNUM_TYPE seldj;
+ EGLPNUM_TYPE selv;
+ EGLPNUM_TYPE c_dj;
+ EGLPNUM_TYPE cmax;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (seldj);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (selv);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (c_dj);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (cmax);
+ EGLPNUM_TYPENAME_EGlpNumZero (c_dj);
+ EGLPNUM_TYPENAME_EGlpNumZero (selv);
+ EGLPNUM_TYPENAME_EGlpNumZero (seldj);
+ EGLPNUM_TYPENAME_ILLbasis_init_vardata (&vd);
+
+ get_var_info (lp, &vd);
+
+ ILL_SAFE_MALLOC (irow, lp->nrows, int);
+ ILL_SAFE_MALLOC (rrow, lp->nrows, int);
+
+ v = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+ ILL_SAFE_MALLOC (unitcol, lp->nrows, int);
+ ILL_SAFE_MALLOC (icol, lp->ncols, int);
+ ILL_SAFE_MALLOC (rcol, lp->ncols, int);
+
+ dj = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->ncols);
+
+ for (i = 0; i < lp->nrows; i++)
+ {
+ unitcol[i] = -1;
+ EGLPNUM_TYPENAME_EGlpNumCopy (v[i], EGLPNUM_TYPENAME_INFTY);
+ irow[i] = 0;
+ rrow[i] = 0;
+ }
+ /* assign all d_j */
+ for (i = 0; i < lp->ncols; i++)
+ {
+ icol[i] = 0;
+ rcol[i] = 0;
+ EGLPNUM_TYPENAME_EGlpNumCopy (dj[i], lp->cz[i]);
+ }
+
+ nslacks = init_slack_basis (lp, vstat, irow, rrow, unitcol, icol, rcol);
+ if (nslacks != vd.nslacks)
+ {
+ QSlog("complain: incorrect basis info");
+ rval = E_SIMPLEX_ERROR;
+ ILL_CLEANUP;
+ }
+ if (nslacks == lp->nrows)
+ ILL_CLEANUP;
+ nbelem = nslacks;
+
+ /* allocate maximum required space for perm etc. */
+ ILL_SAFE_MALLOC (perm, lp->ncols, int);
+ ILL_SAFE_MALLOC (porder, lp->ncols, int);
+ ILL_SAFE_MALLOC (plen, lp->nrows, int);
+
+ qpenalty = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->ncols);
+
+ /* find all unit rows and record lengths */
+ for (i = 0; i < lp->nrows; i++)
+ {
+ if (irow[i] != 1)
+ {
+ rbeg = lp->rowbeg[i];
+ rcnt = lp->rowcnt[i];
+ for (j = 0; j < rcnt; j++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs (cmax, lp->rowval[rbeg + j]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (cmax, EGLPNUM_TYPENAME_oneLpNum))
+ break;
+ }
+ if (j == rcnt)
+ {
+ perm[s_i] = s_i;
+ porder[s_i] = i;
+ plen[s_i] = rcnt;
+ s_i++;
+ }
+ }
+ }
+
+ /*sort all unit rows */
+ ILLutil_int_perm_quicksort (perm, plen, s_i);
+
+ /* now go through the unit rows */
+ for (k = 0; k < s_i; k++)
+ {
+ i = porder[perm[k]];
+ rbeg = lp->rowbeg[i];
+ rcnt = lp->rowcnt[i];
+ selc = -1;
+ EGLPNUM_TYPENAME_EGlpNumCopy (seldj, EGLPNUM_TYPENAME_INFTY);
+ EGLPNUM_TYPENAME_EGlpNumZero (selv);
+
+ /* for every row s_i, compute min {d_j : d_j <0 , j is u or l or fr} */
+ for (j = 0; j < rcnt; j++)
+ {
+ col = lp->rowind[rbeg + j];
+ if (rcol[col] == 1)
+ break;
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (dj[col]))
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (dj[col], seldj))
+ {
+ selc = col;
+ EGLPNUM_TYPENAME_EGlpNumCopy (seldj, dj[col]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (selv, lp->rowval[rbeg + j]);
+ }
+ }
+ }
+ /* select pivot element and update all d_j's */
+ if (selc != -1)
+ {
+ nbelem++;
+ irow[i] = 1;
+ rrow[i] = 1;
+ icol[selc] = 1;
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (c_dj, dj[selc], selv);
+ vstat[selc] = STAT_BASIC;
+ for (j = 0; j < rcnt; j++)
+ {
+ col = lp->rowind[rbeg + j];
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (dj[col], lp->rowval[rbeg + j], c_dj);
+ rcol[col] = 1;
+ }
+ }
+ }
+#if BASIS_STATS > 0
+ QSlog("unit rows = %d", s_i);
+ QSlog("nslacks %d, unit rows selected = %d", nslacks, nbelem - nslacks);
+#endif
+ /* now go through remaining cols with dj = 0 */
+ tot1 = vd.nfree + vd.nbndone;
+
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (vd.cmax))
+ EGLPNUM_TYPENAME_EGlpNumOne (cmax);
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (cmax, vd.cmax);
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (cmax, 1000);
+ }
+ for (j = 0; j < lp->ncols; j++)
+ {
+ if (vstat[j] == STAT_BASIC)
+ continue;
+ if (icol[j] == 1 || EGLPNUM_TYPENAME_EGlpNumIsNeqZero (dj[j], EGLPNUM_TYPENAME_BD_TOLER))
+ continue;
+ mcnt = lp->matcnt[j];
+
+ EGLPNUM_TYPENAME_EGlpNumSet (c_dj, (double) mcnt);
+ switch (lp->vtype[j])
+ {
+ case VFREE:
+ porder[tfree] = j;
+ perm[tfree] = tfree;
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (qpenalty[tfree], lp->cz[j], cmax);
+ EGLPNUM_TYPENAME_EGlpNumAddTo (qpenalty[tfree], c_dj);
+ tfree++;
+ break;
+
+ case VLOWER:
+ case VUPPER:
+ porder[vd.nfree + tbndone] = j;
+ perm[vd.nfree + tbndone] = tbndone;
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (qpenalty[vd.nfree + tbndone], lp->cz[j], cmax);
+ EGLPNUM_TYPENAME_EGlpNumAddTo (qpenalty[vd.nfree + tbndone], c_dj);
+ if (lp->vtype[j] == VLOWER)
+ EGLPNUM_TYPENAME_EGlpNumAddTo (qpenalty[vd.nfree + tbndone], lp->lz[j]);
+ else
+ EGLPNUM_TYPENAME_EGlpNumSubTo (qpenalty[vd.nfree + tbndone], lp->uz[j]);
+ tbndone++;
+ break;
+
+ case VFIXED:
+ case VBOUNDED:
+ porder[tot1 + tbounded] = j;
+ perm[tot1 + tbounded] = tbounded;
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (qpenalty[tot1 + tbounded], lp->cz[j], cmax);
+ EGLPNUM_TYPENAME_EGlpNumAddTo (qpenalty[tot1 + tbounded], lp->lz[j]);
+ EGLPNUM_TYPENAME_EGlpNumSubTo (qpenalty[tot1 + tbounded], lp->uz[j]);
+ EGLPNUM_TYPENAME_EGlpNumAddTo (qpenalty[tot1 + tbounded], c_dj);
+ tbounded++;
+ break;
+ }
+ }
+#if BASIS_STATS > 0
+ QSlog("bfree %d, bone %d, bbnd %d", tfree, tbndone, tbounded);
+#endif
+
+ EGLPNUM_TYPENAME_ILLutil_EGlpNum_perm_quicksort (perm, qpenalty, tfree);
+ EGLPNUM_TYPENAME_ILLutil_EGlpNum_perm_quicksort (perm + vd.nfree, qpenalty + vd.nfree,
+ tbndone);
+ EGLPNUM_TYPENAME_ILLutil_EGlpNum_perm_quicksort (perm + tot1, qpenalty + tot1, tbounded);
+
+ tot2 = tfree + tbndone;
+ for (i = 0; i < tbndone; i++)
+ {
+ perm[tfree + i] = perm[vd.nfree + i] + tfree;
+ porder[tfree + i] = porder[vd.nfree + i];
+ }
+ for (i = 0; i < tbounded; i++)
+ {
+ perm[tot2 + i] = perm[tot1 + i] + tot2;
+ porder[tot2 + i] = porder[tot1 + i];
+ }
+ tot2 += tbounded;
+
+ nbelem =
+ primal_col_select (lp, vstat, irow, rrow, unitcol, v, perm, porder, nbelem,
+ tot2);
+ if (nbelem != lp->nrows)
+ {
+ QSlog("complain: incorrect final basis size");
+ rval = E_SIMPLEX_ERROR;
+ ILL_CLEANUP;
+ }
+
+CLEANUP:
+ if (rval)
+ EGLPNUM_TYPENAME_ILLbasis_free_basisinfo (lp);
+
+ ILL_IFFREE (irow, int);
+ ILL_IFFREE (rrow, int);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (v);
+ ILL_IFFREE (unitcol, int);
+ ILL_IFFREE (icol, int);
+ ILL_IFFREE (rcol, int);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (dj);
+ ILL_IFFREE (perm, int);
+ ILL_IFFREE (porder, int);
+ ILL_IFFREE (plen, int);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (qpenalty);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (seldj);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (selv);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (c_dj);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (cmax);
+ EGLPNUM_TYPENAME_ILLbasis_clear_vardata (&vd);
+ EG_RETURN (rval);
+}
+
+static int set_basis_indices (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int *vstat)
+{
+ int i, b = 0, nb = 0;
+ int vs;
+
+ for (i = 0; i < lp->ncols; i++)
+ {
+ vs = vstat[i];
+ lp->vstat[i] = vs;
+
+ if (vs == STAT_BASIC)
+ {
+ lp->baz[b] = i;
+ lp->vindex[i] = b;
+ b++;
+ }
+ else if (vs == STAT_UPPER || vs == STAT_LOWER || vs == STAT_ZERO)
+ {
+ lp->nbaz[nb] = i;
+ lp->vindex[i] = nb;
+ nb++;
+ }
+ else
+ {
+ QSlog("Error in basis creation");
+ return E_SIMPLEX_ERROR;
+ }
+ }
+ if (b != lp->nrows)
+ {
+ QSlog("Error 2 in basis creation");
+ return E_SIMPLEX_ERROR;
+ }
+ else if (nb != lp->nnbasic)
+ {
+ QSlog("Error 3 in basis creation");
+ return E_SIMPLEX_ERROR;
+ }
+ return 0;
+}
+
+int EGLPNUM_TYPENAME_ILLbasis_get_initial (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int algorithm)
+{
+ int rval = 0;
+ int *vstat = NULL;
+
+ EGLPNUM_TYPENAME_ILLbasis_free_basisinfo (lp);
+ EGLPNUM_TYPENAME_ILLbasis_init_basisinfo (lp);
+ rval = EGLPNUM_TYPENAME_ILLbasis_build_basisinfo (lp);
+ CHECKRVALG (rval, CLEANUP);
+
+ ILL_SAFE_MALLOC (vstat, lp->ncols, int);
+
+ if (algorithm == PRIMAL_SIMPLEX)
+ rval = get_initial_basis1 (lp, vstat);
+ else
+ rval = get_initial_basis2 (lp, vstat);
+
+ if (rval == E_SIMPLEX_ERROR)
+ {
+#ifdef HAVE_LIBZ
+ EGioFile_t *f = EGioOpen ("bad.lp.gz", "w");
+#else
+#ifdef HAVE_LIBBZ2
+ EGioFile_t *f = EGioOpen ("bad.lp.bz2", "w");
+#else
+ EGioFile_t *f = EGioOpen ("bad.lp", "w");
+#endif
+#endif
+ int tval = EGLPNUM_TYPENAME_ILLwrite_lp_file (lp->O, f, NULL);
+ if (tval)
+ {
+ QSlog("Error writing bad lp");
+ }
+ if (f != NULL)
+ EGioClose (f);
+ }
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = set_basis_indices (lp, vstat);
+ CHECKRVALG (rval, CLEANUP);
+ lp->basisid = 0;
+
+CLEANUP:
+ ILL_IFFREE (vstat, int);
+
+ EG_RETURN (rval);
+}
+
+static int choose_basis (
+ int algorithm,
+ EGLPNUM_TYPE pinf1,
+ EGLPNUM_TYPE dinf1,
+ EGLPNUM_TYPE pinf2,
+ EGLPNUM_TYPE dinf2)
+{
+/* We changed the constant definitions outside here, the actual numbers are
+ * asigned in lpdata.c. the values are as follows:
+ * EGLPNUM_TYPENAME_CB_EPS = 0.001;
+ * EGLPNUM_TYPENAME_CB_PRI_RLIMIT = 0.25;
+ * EGLPNUM_TYPENAME_CB_INF_RATIO = 10.0;
+ * */
+ int choice = 1;
+ EGLPNUM_TYPE rp, rd;
+
+ if (algorithm == PRIMAL_SIMPLEX)
+ {
+ EGLPNUM_TYPENAME_EGlpNumInitVar (rp);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (rd);
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (rp, pinf1, pinf2);
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (rd, dinf1, dinf2);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLeq (rp, EGLPNUM_TYPENAME_CB_EPS) && EGLPNUM_TYPENAME_EGlpNumIsLeq (rd, EGLPNUM_TYPENAME_CB_EPS))
+ choice = 1;
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumSign (rp);
+ EGLPNUM_TYPENAME_EGlpNumSign (rd);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLeq (rp, EGLPNUM_TYPENAME_CB_EPS) && EGLPNUM_TYPENAME_EGlpNumIsLeq (rd, EGLPNUM_TYPENAME_CB_EPS))
+ choice = 2;
+ else if (EGLPNUM_TYPENAME_EGlpNumIsLess (pinf1, pinf2) && EGLPNUM_TYPENAME_EGlpNumIsLess (dinf2, dinf1))
+ {
+ choice = 1;
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (rp, pinf1, pinf2);
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (rd, dinf2, dinf1);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (rd, EGLPNUM_TYPENAME_CB_INF_RATIO);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_CB_PRI_RLIMIT, rp) && (EGLPNUM_TYPENAME_EGlpNumIsLess (rd, rp)))
+ choice = 2;
+ }
+ else if (EGLPNUM_TYPENAME_EGlpNumIsLess (pinf2, pinf1) && EGLPNUM_TYPENAME_EGlpNumIsLess (dinf1, dinf2))
+ {
+ choice = 2;
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (rp, pinf2, pinf1);
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (rd, dinf1, dinf2);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (rd, EGLPNUM_TYPENAME_CB_INF_RATIO);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_CB_PRI_RLIMIT, rp) && EGLPNUM_TYPENAME_EGlpNumIsLess (rd, rp))
+ choice = 1;
+ }
+ else
+ choice = 1;
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (rp);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (rd);
+ }
+ ILL_IFTRACE ("%s:%d\n", __func__, choice);
+ return choice;
+}
+
+int EGLPNUM_TYPENAME_ILLbasis_get_cinitial (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int algorithm)
+{
+ int rval = 0;
+ int *vstat1 = NULL;
+ int *vstat2 = NULL;
+ int singular;
+ int choice = 0;
+
+#if BASIS_STATS > 0
+ int i, nz1 = 0, nz2 = 0;
+#endif
+ EGLPNUM_TYPE pinf1, pinf2, dinf1, dinf2;
+ EGLPNUM_TYPENAME_feas_info fi;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (pinf1);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (pinf2);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (dinf1);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (dinf2);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (fi.totinfeas);
+
+ EGLPNUM_TYPENAME_ILLbasis_free_basisinfo (lp);
+ EGLPNUM_TYPENAME_ILLbasis_init_basisinfo (lp);
+ rval = EGLPNUM_TYPENAME_ILLbasis_build_basisinfo (lp);
+ CHECKRVALG (rval, CLEANUP);
+
+ ILL_SAFE_MALLOC (vstat1, lp->ncols, int);
+ ILL_SAFE_MALLOC (vstat2, lp->ncols, int);
+
+ if (algorithm != PRIMAL_SIMPLEX)
+ {
+ rval = get_initial_basis2 (lp, vstat2);
+ CHECKRVALG (rval, CLEANUP);
+ rval = set_basis_indices (lp, vstat2);
+ lp->basisid = 0;
+ ILL_CLEANUP;
+ }
+
+ rval = get_initial_basis1 (lp, vstat1);
+ CHECKRVALG (rval, CLEANUP);
+ rval = get_initial_basis2 (lp, vstat2);
+ CHECKRVALG (rval, CLEANUP);
+ lp->basisid = 0;
+
+ /* handle first basis */
+ rval = set_basis_indices (lp, vstat1);
+ CHECKRVALG (rval, CLEANUP);
+#if BASIS_STATS > 0
+ for (i = 0; i < lp->nrows; i++)
+ nz1 += lp->matcnt[lp->baz[i]];
+#endif
+ rval = EGLPNUM_TYPENAME_ILLbasis_factor (lp, &singular);
+ if (singular)
+ MESSAGE (__QS_SB_VERB, "Singular Basis found!");
+ CHECKRVALG (rval, CLEANUP);
+
+ EGLPNUM_TYPENAME_ILLfct_compute_piz (lp);
+ EGLPNUM_TYPENAME_ILLfct_compute_dz (lp);
+ EGLPNUM_TYPENAME_ILLfct_dual_adjust (lp, EGLPNUM_TYPENAME_zeroLpNum);
+ EGLPNUM_TYPENAME_ILLfct_compute_xbz (lp);
+
+ EGLPNUM_TYPENAME_ILLfct_check_pfeasible (lp, &fi, lp->tol->pfeas_tol);
+ EGLPNUM_TYPENAME_ILLfct_check_dfeasible (lp, &fi, lp->tol->dfeas_tol);
+ EGLPNUM_TYPENAME_EGlpNumCopy (pinf1, lp->pinfeas);
+ EGLPNUM_TYPENAME_EGlpNumCopy (dinf1, lp->dinfeas);
+ /*
+ * EGLPNUM_TYPENAME_ILLfct_compute_pobj (lp); obj1p = lp->objval;
+ * EGLPNUM_TYPENAME_ILLfct_compute_dobj (lp); obj1d = lp->objval;
+ */
+
+ /* handle second basis */
+ rval = set_basis_indices (lp, vstat2);
+ CHECKRVALG (rval, CLEANUP);
+#if BASIS_STATS > 0
+ for (i = 0; i < lp->nrows; i++)
+ nz2 += lp->matcnt[lp->baz[i]];
+#endif
+ rval = EGLPNUM_TYPENAME_ILLbasis_factor (lp, &singular);
+ if (singular)
+ MESSAGE (__QS_SB_VERB, "Singular Basis found!");
+ CHECKRVALG (rval, CLEANUP);
+
+ EGLPNUM_TYPENAME_ILLfct_compute_piz (lp);
+ EGLPNUM_TYPENAME_ILLfct_compute_dz (lp);
+ EGLPNUM_TYPENAME_ILLfct_dual_adjust (lp, EGLPNUM_TYPENAME_zeroLpNum);
+ EGLPNUM_TYPENAME_ILLfct_compute_xbz (lp);
+
+ EGLPNUM_TYPENAME_ILLfct_check_pfeasible (lp, &fi, lp->tol->pfeas_tol);
+ EGLPNUM_TYPENAME_ILLfct_check_dfeasible (lp, &fi, lp->tol->dfeas_tol);
+ EGLPNUM_TYPENAME_EGlpNumCopy (pinf2, lp->pinfeas);
+ EGLPNUM_TYPENAME_EGlpNumCopy (dinf2, lp->dinfeas);
+
+#if BASIS_STATS > 0
+ QSlog("b1: nz %d pinf %.2f dinf %.2f", nz1, EGLPNUM_TYPENAME_EGlpNumToLf (pinf1),
+ EGLPNUM_TYPENAME_EGlpNumToLf (dinf1));
+ QSlog("b2: nz %d pinf %.2f dinf %.2f", nz2, EGLPNUM_TYPENAME_EGlpNumToLf (pinf2),
+ EGLPNUM_TYPENAME_EGlpNumToLf (dinf2));
+#endif
+ choice = choose_basis (algorithm, pinf1, dinf1, pinf2, dinf2);
+ if (choice == 1)
+ {
+ lp->fbasisid = -1;
+ rval = set_basis_indices (lp, vstat1);
+ CHECKRVALG (rval, CLEANUP);
+ }
+
+CLEANUP:
+ if (rval == E_SIMPLEX_ERROR)
+ {
+#ifdef HAVE_LIBZ
+ EGioFile_t *fil = EGioOpen ("bad.lp.gz", "w");
+#else
+#ifdef HAVE_LIBBZ2
+ EGioFile_t *fil = EGioOpen ("bad.lp.bz2", "w");
+#else
+ EGioFile_t *fil = EGioOpen ("bad.lp", "w");
+#endif
+#endif
+ int tval = EGLPNUM_TYPENAME_ILLwrite_lp_file (lp->O, fil, NULL);
+
+ if (tval)
+ {
+ QSlog("Error writing bad lp");
+ }
+ if (fil != NULL)
+ EGioClose (fil);
+ }
+ ILL_IFFREE (vstat1, int);
+ ILL_IFFREE (vstat2, int);
+
+ EGLPNUM_TYPENAME_EGlpNumClearVar (pinf1);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (pinf2);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (dinf1);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (dinf2);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (fi.totinfeas);
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLbasis_factor (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int *singular)
+{
+ int rval = 0;
+ int i;
+ int eindex;
+ int lindex;
+ int ltype;
+ int lvstat;
+ int nsing = 0;
+ int *singr = 0;
+ int *singc = 0;
+
+ *singular = 0;
+ do
+ {
+ if (lp->f)
+ {
+ EGLPNUM_TYPENAME_ILLfactor_free_factor_work (lp->f);
+ }
+ else
+ {
+ ILL_SAFE_MALLOC (lp->f, 1, EGLPNUM_TYPENAME_factor_work);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (lp->f->fzero_tol);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (lp->f->szero_tol);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (lp->f->partial_tol);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (lp->f->maxelem_orig);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (lp->f->maxelem_factor);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (lp->f->maxelem_cur);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (lp->f->partial_cur);
+ EGLPNUM_TYPENAME_ILLfactor_init_factor_work (lp->f);
+ }
+ rval = EGLPNUM_TYPENAME_ILLfactor_create_factor_work (lp->f, lp->O->nrows);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLfactor (lp->f, lp->baz, lp->matbeg, lp->matcnt,
+ lp->matind, lp->matval, &nsing, &singr, &singc);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (nsing != 0)
+ {
+ *singular = 1;
+ MESSAGE (__QS_SB_VERB, "Found singular basis!");
+ for (i = 0; i < nsing; i++)
+ {
+ eindex = lp->vindex[lp->O->rowmap[singr[i]]];
+ lindex = singc[i];
+ ltype = lp->vtype[lp->baz[lindex]];
+
+ if (ltype == VBOUNDED || ltype == VLOWER || ltype == VARTIFICIAL)
+ lvstat = STAT_LOWER;
+ else if (ltype == VUPPER)
+ lvstat = STAT_UPPER;
+ else
+ lvstat = STAT_ZERO;
+
+ EGLPNUM_TYPENAME_ILLfct_update_basis_info (lp, eindex, lindex, lvstat);
+ lp->basisid++;
+ }
+ ILL_IFFREE (singr, int);
+ ILL_IFFREE (singc, int);
+ }
+
+ } while (nsing != 0);
+
+ lp->fbasisid = lp->basisid;
+
+CLEANUP:
+ ILL_IFFREE (singr, int);
+ ILL_IFFREE (singc, int);
+
+ if (rval)
+ QSlog("Error: unknown in %s", __func__);
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLbasis_refactor (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ int sing = 0;
+ int rval = 0;
+
+ rval = EGLPNUM_TYPENAME_ILLbasis_factor (lp, &sing);
+ if (sing)
+ {
+ MESSAGE (__QS_SB_VERB, "Singular Basis found!");
+ rval = QS_LP_CHANGE_PREC;
+ return rval;
+ }
+ EG_RETURN (rval);
+}
+
+void EGLPNUM_TYPENAME_ILLbasis_column_solve (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * rhs,
+ EGLPNUM_TYPENAME_svector * soln)
+{
+ EGLPNUM_TYPENAME_ILLfactor_ftran (lp->f, rhs, soln);
+}
+
+void EGLPNUM_TYPENAME_ILLbasis_column_solve_update (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * rhs,
+ EGLPNUM_TYPENAME_svector * upd,
+ EGLPNUM_TYPENAME_svector * soln)
+{
+ EGLPNUM_TYPENAME_ILLfactor_ftran_update (lp->f, rhs, upd, soln);
+}
+
+void EGLPNUM_TYPENAME_ILLbasis_row_solve (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * rhs,
+ EGLPNUM_TYPENAME_svector * soln)
+{
+ EGLPNUM_TYPENAME_ILLfactor_btran (lp->f, rhs, soln);
+}
+
+int EGLPNUM_TYPENAME_ILLbasis_update (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * y,
+ int lindex,
+ int *refactor,
+ int *singular)
+{
+#if 0 /* To always refactor, change 0 to 1 */
+ *refactor = 1;
+ return EGLPNUM_TYPENAME_ILLbasis_factor (lp, singular);
+#else
+
+ int rval = 0;
+
+ *refactor = 0;
+ rval = EGLPNUM_TYPENAME_ILLfactor_update (lp->f, y, lindex, refactor);
+ if (rval == E_FACTOR_BLOWUP || rval == E_UPDATE_SINGULAR_ROW
+ || rval == E_UPDATE_SINGULAR_COL)
+ {
+/* Bico - comment out for dist
+ QSlog("Warning: numerically bad basis in EGLPNUM_TYPENAME_ILLfactor_update");
+*/
+ *refactor = 1;
+ rval = 0;
+ }
+ if (rval == E_UPDATE_NOSPACE)
+ {
+ *refactor = 1;
+ rval = 0;
+ }
+
+ if (*refactor)
+ {
+ rval = EGLPNUM_TYPENAME_ILLbasis_factor (lp, singular);
+ if (*singular)
+ MESSAGE (__QS_SB_VERB, "Singular Basis found!");
+ }
+ if (rval)
+ {
+ EGioFile_t *eout = 0;
+ int tval;
+
+ QSlog("write bad lp to factor.lp");
+#ifdef HAVE_LIBZ
+ eout = EGioOpen ("factor.lp.gz", "w");
+#else
+#ifdef HAVE_LIBBZ2
+ eout = EGioOpen ("factor.lp.bz2", "w");
+#else
+ eout = EGioOpen ("factor.lp", "w");
+#endif
+#endif
+ if (!eout)
+ {
+ QSlog("could not open file to write bad factor lp");
+ }
+ else
+ {
+ tval = EGLPNUM_TYPENAME_ILLwrite_lp_file (lp->O, eout, NULL);
+ if (tval)
+ {
+ QSlog("error while writing bad factor lp");
+ }
+ EGioClose (eout);
+ }
+
+ QSlog("write bad basis to factor.bas");
+ tval = EGLPNUM_TYPENAME_ILLlib_writebasis (lp, 0, "factor.bas");
+ if (tval)
+ {
+ QSlog("error while writing factor basis");
+ }
+ }
+
+ EG_RETURN (rval);
+#endif
+}
diff --git a/qsopt_ex/basis.h b/qsopt_ex/basis.h
new file mode 100644
index 0000000..9d073be
--- /dev/null
+++ b/qsopt_ex/basis.h
@@ -0,0 +1,99 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCSINFO $Id: basis_EGLPNUM_TYPENAME.h,v 1.3 2003/11/05 16:57:39 meven Exp $ */
+#ifndef EGLPNUM_TYPENAME___BASIS_H
+#define EGLPNUM_TYPENAME___BASIS_H
+
+#include "dstruct_EGLPNUM_TYPENAME.h"
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+#include "lpdata_EGLPNUM_TYPENAME.h"
+
+
+typedef struct EGLPNUM_TYPENAME_var_data
+{
+ int nartif;
+ int nslacks;
+ int nfree;
+ int nbndone;
+ int nbounded;
+ int nfixed;
+ EGLPNUM_TYPE cmax;
+}
+EGLPNUM_TYPENAME_var_data;
+
+void EGLPNUM_TYPENAME_ILLbasis_init_vardata (
+ EGLPNUM_TYPENAME_var_data * vd);
+void EGLPNUM_TYPENAME_ILLbasis_clear_vardata (
+ EGLPNUM_TYPENAME_var_data * vd);
+
+int EGLPNUM_TYPENAME_ILLbasis_build_basisinfo (
+ EGLPNUM_TYPENAME_lpinfo * lp),
+ EGLPNUM_TYPENAME_ILLbasis_get_initial (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int algorithm),
+ EGLPNUM_TYPENAME_ILLbasis_get_cinitial (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int algorithm),
+ EGLPNUM_TYPENAME_ILLbasis_load (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_ILLlp_basis * B),
+ EGLPNUM_TYPENAME_ILLbasis_tableau_row (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int row,
+ EGLPNUM_TYPE * brow,
+ EGLPNUM_TYPE * trow,
+ EGLPNUM_TYPE * rhs,
+ int strict),
+ EGLPNUM_TYPENAME_ILLbasis_factor (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int *singular),
+ EGLPNUM_TYPENAME_ILLbasis_refactor (
+ EGLPNUM_TYPENAME_lpinfo * lp),
+ EGLPNUM_TYPENAME_ILLbasis_update (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * y,
+ int lindex,
+ int *refactor,
+ int *singular);
+
+void EGLPNUM_TYPENAME_ILLbasis_column_solve (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * rhs,
+ EGLPNUM_TYPENAME_svector * soln),
+ EGLPNUM_TYPENAME_ILLbasis_column_solve_update (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * rhs,
+ EGLPNUM_TYPENAME_svector * upd,
+ EGLPNUM_TYPENAME_svector * soln),
+ EGLPNUM_TYPENAME_ILLbasis_row_solve (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * rhs,
+ EGLPNUM_TYPENAME_svector * soln),
+ EGLPNUM_TYPENAME_ILLbasis_free_basisinfo (
+ EGLPNUM_TYPENAME_lpinfo * lp),
+ EGLPNUM_TYPENAME_ILLbasis_free_fbasisinfo (
+ EGLPNUM_TYPENAME_lpinfo * lp),
+ EGLPNUM_TYPENAME_ILLbasis_init_basisinfo (
+ EGLPNUM_TYPENAME_lpinfo * lp);
+
+#endif /* EGLPNUM_TYPENAME___BASIS_H */
diff --git a/qsopt_ex/bgetopt.c b/qsopt_ex/bgetopt.c
new file mode 100644
index 0000000..3ba4564
--- /dev/null
+++ b/qsopt_ex/bgetopt.c
@@ -0,0 +1,132 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCSINFO $Id: bgetopt.c,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+/****************************************************************************/
+/* */
+/* This file is part of CONCORDE */
+/* */
+/* (c) Copyright 1995--1999 by David Applegate, Robert Bixby, */
+/* Vasek Chvatal, and William Cook */
+/* */
+/* Permission is granted for academic research use. For other uses, */
+/* contact the authors for licensing options. */
+/* */
+/* Use at your own risk. We make no guarantees about the */
+/* correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* PORTABLE GETOPT */
+/* */
+/* TSP CODE */
+/* */
+/* */
+/* Written by: Applegate, Bixby, Chvatal, and Cook */
+/* Date: 1993 (?) (fmfeb02) */
+/* Modified: 15 February 1995 (bico) - added warning */
+/* */
+/* EXPORTED FUNCTIONS: */
+/* */
+/* int ILLutil_bix_getopt (int argc, char **argv, const char *def, */
+/* int *p_optind, char **p_optarg) */
+/* parse an argument list */
+/* */
+/****************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "logging-private.h"
+
+#include "util.h"
+
+
+int ILLutil_bix_getopt (
+ int ac,
+ char **av,
+ const char *def,
+ int *p_optind,
+ char **p_optarg)
+{
+ int c;
+ char *sp = av[*p_optind];
+ char bwarn[2];
+
+ if (*p_optind < 1 || *p_optind >= ac)
+ {
+ *p_optind = ac;
+ return (EOF);
+ }
+ if ((int) *sp != (int) '-')
+ return (EOF);
+ if ((int) *(sp + 1) == (int) '-')
+ {
+ (*p_optind)++;
+ return (EOF);
+ }
+ (av[*p_optind])++;
+ sp++;
+ while ((int) *sp != (int) *def && (int) *def != (int) '\0')
+ def++;
+ if ((int) *def == (int) '\0')
+ {
+ *p_optind = ac;
+ bwarn[0] = *sp; /* Bico: February 8, 1995 */
+ bwarn[1] = '\0';
+ QSlog("Illegal option: -%s", bwarn);
+ return ILL_BIX_GETOPT_UNKNOWN;
+ }
+ if ((int) *(def + 1) != (int) ':')
+ {
+ c = *sp;
+ if ((int) *(sp + 1) != (int) '\0')
+ *sp = '-';
+ else
+ (*p_optind)++;
+ return (c);
+ }
+ else
+ {
+ if ((int) *(sp + 1) != (int) '\0')
+ {
+ *p_optarg = sp + 1;
+ c = *sp;
+ (*p_optind)++;
+ return (c);
+ }
+ else if (*p_optind >= ac - 1)
+ {
+ *p_optind = ac;
+ return (EOF);
+ }
+ else
+ {
+ *p_optarg = av[*p_optind + 1];
+ c = *sp;
+ *p_optind += 2;
+ return (c);
+ }
+ }
+}
diff --git a/qsopt_ex/bgetopt.h b/qsopt_ex/bgetopt.h
new file mode 100644
index 0000000..6ec0cf0
--- /dev/null
+++ b/qsopt_ex/bgetopt.h
@@ -0,0 +1,43 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+#ifndef __BGETOPT_H__
+#define __BGETOPT_H__
+
+/****************************************************************************/
+/* */
+/* bgetopt.c */
+/* */
+/****************************************************************************/
+int ILLutil_bix_getopt (
+ int argc,
+ char **argv,
+ const char *def,
+ int *p_optind,
+ char **p_optarg);
+
+
+#define ILL_BIX_GETOPT_UNKNOWN -3038
+
+
+
+#endif
diff --git a/qsopt_ex/binary.c b/qsopt_ex/binary.c
new file mode 100644
index 0000000..56363bb
--- /dev/null
+++ b/qsopt_ex/binary.c
@@ -0,0 +1,1756 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: binary.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+static int TRACE = 0;
+
+/****************************************************************************/
+/* */
+/* Simple MIP Code to test LP Solver */
+/* */
+/* EXPORTED FUNCTIONS */
+/* */
+/* int EGLPNUM_TYPENAME_ILLmip_bfs (EGLPNUM_TYPENAME_lpinfo *lp, double *val, double *x) */
+/* */
+/* NOTES */
+/* */
+/* */
+/****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "allocrus.h"
+#include "eg_lpnum.h"
+#include "eg_io.h"
+#include "except.h"
+#include "zeit.h"
+
+#include "priority_EGLPNUM_TYPENAME.h"
+#include "sortrus_EGLPNUM_TYPENAME.h"
+#include "lpdata_EGLPNUM_TYPENAME.h"
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+#include "simplex_EGLPNUM_TYPENAME.h"
+#include "binary_EGLPNUM_TYPENAME.h"
+#include "price_EGLPNUM_TYPENAME.h"
+#include "lib_EGLPNUM_TYPENAME.h"
+#include "qstruct_EGLPNUM_TYPENAME.h"
+#include "qsopt_EGLPNUM_TYPENAME.h"
+
+/*#define ILL_INTTOL (0.000001)*/
+#define ILL_INTTOL EGLPNUM_TYPENAME_PFEAS_TOLER
+
+#define STRONG_PIVOTS (50)
+#define STRONG_CANDIDATES (10)
+
+#define ILL_BRANCH_STRONG_WEIGHT (10)
+#define ILL_BRANCH_STRONG_VAL(v0,v1) \
+ (((v0) < (v1) ? (ILL_BRANCH_STRONG_WEIGHT * (v0) + (v1)) \
+ : (ILL_BRANCH_STRONG_WEIGHT * (v1) + (v0))) \
+ / (ILL_BRANCH_STRONG_WEIGHT + 1.0))
+
+#define ILL_BRANCH_PENALTY_WEIGHT (2)
+#define ILL_BRANCH_PENALTY_VAL(v0,v1,f) \
+ (((v0)*(f) < (v1)*(1.0-(f)) ? \
+ (ILL_BRANCH_PENALTY_WEIGHT * (v0)*(f) + (v1)*(1.0-(f))) \
+ : (ILL_BRANCH_PENALTY_WEIGHT * (v1)*(1.0-(f)) + (v0)*(f))) \
+ / (ILL_BRANCH_PENALTY_WEIGHT + 1.0))
+
+
+
+#define FIRSTBRANCH 1
+#define MIDDLEBRANCH 2
+#define STRONGBRANCH 3
+#define PENALTYBRANCH 4
+
+
+typedef struct bbnode
+{
+ struct bbnode *next;
+ struct bbnode *prev;
+ int id;
+ int depth;
+ int handle;
+ EGLPNUM_TYPE bound;
+ char *cstat;
+ char *rstat;
+ EGLPNUM_TYPE *rownorms;
+ int rownorms_size;
+ int bound_cnt;
+ int *bound_indx;
+ char *lu;
+ EGLPNUM_TYPE *bounds;
+ int bounds_size;
+}
+bbnode;
+
+typedef struct mipinfo
+{
+ int branching_rule;
+ int watch;
+ int depth;
+ int totalnodes;
+ int activenodes;
+ int totalpivots;
+ int lastpivots;
+ int objsense;
+ EGLPNUM_TYPE objectivebound;
+ EGLPNUM_TYPE value;
+ EGLPNUM_TYPE *downpen;
+ EGLPNUM_TYPE *uppen;
+ EGLPNUM_TYPE *x;
+ EGLPNUM_TYPE *bestx;
+ EGLPNUM_TYPE *orig_lower;
+ EGLPNUM_TYPE *orig_upper;
+ EGLPNUM_TYPE *lower;
+ EGLPNUM_TYPE *upper;
+ int nstruct; /* size of all EGLPNUM_TYPE arrays */
+ EGLPNUM_TYPENAME_lpinfo *lp;
+ EGLPNUM_TYPENAME_price_info *pinf;
+ bbnode head_bbnode;
+ EGLPNUM_TYPENAME_ILLpriority *que;
+ ILLptrworld ptrworld;
+}
+mipinfo;
+
+
+ILL_PTRWORLD_ROUTINES (bbnode, bbnodealloc, bbnode_bulkalloc, bbnodefree)
+ILL_PTRWORLD_LISTFREE_ROUTINE (bbnode, bbnode_listfree, bbnodefree)
+ILL_PTRWORLD_LEAKS_ROUTINE (bbnode, bbnode_check_leaks, depth, int)
+static void cleanup_mip ( mipinfo * minf),
+ choose_initial_price ( EGLPNUM_TYPENAME_price_info * pinf),
+ best_bbnode ( mipinfo * minf, bbnode ** best),
+ put_bbnode ( mipinfo * minf, bbnode * b),
+ remove_bbnode ( bbnode * b),
+ find_first_branch ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPE * x, int *bvar),
+ find_middle_branch ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPE * x, int *bvar),
+ check_integral ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPE * x, int *yesno),
+ copy_x ( int nstruct, EGLPNUM_TYPE * from_x, EGLPNUM_TYPE * to_x),
+ init_mipinfo ( mipinfo * minf),
+ free_mipinfo ( mipinfo * minf),
+ init_bbnode ( bbnode * b),
+ free_bbnode ( bbnode * b);
+
+static int startup_mip ( mipinfo * minf, EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_price_info * pinf,
+ EGLPNUM_TYPE * lpval, itcnt_t*itcnt),
+ run_bfs ( mipinfo * minf, itcnt_t*itcnt),
+ process_bfs_bbnode ( mipinfo * minf, bbnode * b, itcnt_t*itcnt),
+ child_work ( mipinfo * minf, bbnode * active, int bvar, int bdir,
+ EGLPNUM_TYPE * cval, int *cp, itcnt_t*itcnt),
+ fix_variables ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPE * bestval, bbnode * b,
+ EGLPNUM_TYPE * wupper, EGLPNUM_TYPE * wlower, int *hit),
+ find_branch ( mipinfo * minf, EGLPNUM_TYPE * x, EGLPNUM_TYPE * lpval,
+ int *bvar, itcnt_t*itcnt),
+ find_penalty_branch ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_price_info * pinf, EGLPNUM_TYPE * x,
+ EGLPNUM_TYPE * downpen, EGLPNUM_TYPE * uppen, EGLPNUM_TYPE * lpval, int *bvar,
+ itcnt_t*itcnt),
+ find_strong_branch ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_price_info * pinf, EGLPNUM_TYPE * x,
+ int *bvar, itcnt_t*itcnt),
+ plunge ( mipinfo * minf, itcnt_t*itcnt),
+ plunge_work ( mipinfo * minf, int depth, itcnt_t*itcnt),
+ round_variables ( mipinfo * minf, int *count, EGLPNUM_TYPE * tol);
+
+static void choose_initial_price ( EGLPNUM_TYPENAME_price_info * pinf)
+{
+ pinf->pI_price = QS_PRICE_PSTEEP;
+ pinf->pII_price = QS_PRICE_PSTEEP;
+ pinf->dI_price = QS_PRICE_DSTEEP;
+ pinf->dII_price = QS_PRICE_DSTEEP;
+}
+
+int EGLPNUM_TYPENAME_ILLmip_bfs (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPE * val,
+ EGLPNUM_TYPE * x,
+ itcnt_t*itcnt)
+{
+ int tval, rval = 0;
+ EGLPNUM_TYPENAME_price_info pinf;
+ mipinfo minf;
+ bbnode *b;
+ EGLPNUM_TYPE lpval;
+ double szeit = ILLutil_zeit ();
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (lpval);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (pinf.htrigger);
+
+ EGLPNUM_TYPENAME_ILLprice_init_pricing_info (&pinf);
+ init_mipinfo (&minf);
+
+ if (!lp)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLmip_bfs called without an LP");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ rval = startup_mip (&minf, lp, &pinf, &lpval, itcnt);
+ ILL_CLEANUP_IF (rval);
+
+ ILL_SAFE_MALLOC (minf.que, 1, EGLPNUM_TYPENAME_ILLpriority);
+ rval = EGLPNUM_TYPENAME_ILLutil_priority_init (minf.que, lp->O->nstruct + 1);
+ ILL_CLEANUP_IF (rval);
+
+ b = bbnodealloc (&minf.ptrworld);
+ init_bbnode (b);
+ b->depth = 0;
+ b->id = minf.totalnodes++;
+ EGLPNUM_TYPENAME_EGlpNumCopy (b->bound, lpval);
+ ILL_SAFE_MALLOC (b->cstat, lp->O->nstruct, char);
+ ILL_SAFE_MALLOC (b->rstat, lp->nrows, char);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_getbasis (lp, b->cstat, b->rstat);
+ ILL_CLEANUP_IF (rval);
+
+ if (pinf.dII_price == QS_PRICE_DSTEEP)
+ {
+ b->rownorms = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+ tval = EGLPNUM_TYPENAME_ILLlib_getrownorms (lp, &pinf, b->rownorms);
+ if (tval)
+ {
+ QSlog("Row norms not available");
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (b->rownorms);
+ }
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLutil_priority_insert (minf.que, (void *) b, &lpval, &(b->handle));
+ ILL_CLEANUP_IF (rval);
+
+ b->prev = &(minf.head_bbnode);
+ b->next = 0;
+ minf.head_bbnode.next = b;
+ minf.activenodes++;
+
+ minf.branching_rule = PENALTYBRANCH;
+
+ rval = run_bfs (&minf, itcnt);
+ ILL_CLEANUP_IF (rval);
+
+ QSlog("Total Number of Nodes: %d", minf.totalnodes);
+ QSlog("Total Number of Pivots: %d", minf.totalpivots);
+ QSlog("BFS MIP Runing Time: %.2f seconds", ILLutil_zeit () - szeit);
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (*val, minf.value);
+ if (minf.objsense == EGLPNUM_TYPENAME_ILL_MAX)
+ EGLPNUM_TYPENAME_EGlpNumSign (*val);
+
+ if (x && EGLPNUM_TYPENAME_EGlpNumIsNeqq (minf.value, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+ {
+ copy_x (lp->O->nstruct, minf.bestx, x);
+ }
+
+CLEANUP:
+
+ if (minf.que)
+ {
+ EGLPNUM_TYPENAME_ILLutil_priority_free (minf.que);
+ ILL_IFFREE (minf.que, EGLPNUM_TYPENAME_ILLpriority);
+ }
+ cleanup_mip (&minf);
+ free_mipinfo (&minf);
+ EGLPNUM_TYPENAME_ILLprice_free_pricing_info (&pinf);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (lpval);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (pinf.htrigger);
+ ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLmip_bfs");
+}
+
+static int startup_mip (
+ mipinfo * minf,
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * pinf,
+ EGLPNUM_TYPE * lpval,
+ itcnt_t*itcnt)
+{
+ int rval = 0;
+ int i, col, status, intcount = 0;
+ EGLPNUM_TYPE val;
+ EGLPNUM_TYPENAME_ILLlpdata *qlp;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (val);
+
+ choose_initial_price (pinf);
+
+ qlp = lp->O;
+
+ rval = EGLPNUM_TYPENAME_ILLlib_optimize (lp, 0, pinf, DUAL_SIMPLEX, &status, 0, itcnt);
+ ILL_CLEANUP_IF (rval);
+
+ minf->totalpivots += EGLPNUM_TYPENAME_ILLlib_iter (lp);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_objval (lp, 0, &val);
+ ILL_CLEANUP_IF (rval);
+
+ QSlog("LP Value: %.6f", EGLPNUM_TYPENAME_EGlpNumToLf (val));
+ if (lpval)
+ EGLPNUM_TYPENAME_EGlpNumCopy (*lpval, val);
+
+ if (qlp->intmarker)
+ {
+ for (i = 0; i < qlp->nstruct; i++)
+ {
+ if (qlp->intmarker[i])
+ {
+ col = qlp->structmap[i];
+ intcount++;
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (qlp->lower[col], EGLPNUM_TYPENAME_ILL_MINDOUBLE)
+ || EGLPNUM_TYPENAME_EGlpNumIsEqqual (qlp->upper[col], EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+ {
+ QSlog("Instance has unbounded integer variable");
+ rval = 1;
+ goto CLEANUP;
+ }
+ }
+ }
+ }
+
+ if (intcount == 0)
+ {
+ QSlog("No integer variables");
+ rval = 1;
+ goto CLEANUP;
+ }
+ else
+ {
+ QSlog("%d integer variables", intcount);
+ }
+
+ if (qlp->sinfo)
+ { /* Free the presolve LP and work with orginal */
+ EGLPNUM_TYPENAME_ILLlp_sinfo_free (qlp->sinfo);
+ ILL_IFFREE (qlp->sinfo, EGLPNUM_TYPENAME_ILLlp_sinfo);
+ }
+
+
+ minf->lp = lp;
+ minf->pinf = pinf;
+ minf->objsense = qlp->objsense;
+ if (qlp->objsense == EGLPNUM_TYPENAME_ILL_MAX)
+ { /* MIP codes work with min */
+ for (i = 0; i < lp->ncols; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyNeg (qlp->obj[i], qlp->obj[i]);
+ }
+ qlp->objsense = EGLPNUM_TYPENAME_ILL_MIN;
+ }
+
+ minf->x = EGLPNUM_TYPENAME_EGlpNumAllocArray (qlp->nstruct);
+ minf->bestx = EGLPNUM_TYPENAME_EGlpNumAllocArray (qlp->nstruct);
+ minf->lower = EGLPNUM_TYPENAME_EGlpNumAllocArray (qlp->nstruct);
+ minf->upper = EGLPNUM_TYPENAME_EGlpNumAllocArray (qlp->nstruct);
+ minf->orig_lower = EGLPNUM_TYPENAME_EGlpNumAllocArray (qlp->nstruct);
+ minf->orig_upper = EGLPNUM_TYPENAME_EGlpNumAllocArray (qlp->nstruct);
+ minf->downpen = EGLPNUM_TYPENAME_EGlpNumAllocArray (qlp->nstruct);
+ minf->uppen = EGLPNUM_TYPENAME_EGlpNumAllocArray (qlp->nstruct);
+ minf->nstruct = qlp->nstruct;
+
+ rval = EGLPNUM_TYPENAME_ILLlib_get_x (lp, 0, minf->x);
+ ILL_CLEANUP_IF (rval);
+
+ for (i = 0; i < qlp->nstruct; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (minf->lower[i], qlp->lower[i]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (minf->upper[i], qlp->upper[i]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (minf->orig_lower[i], qlp->lower[i]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (minf->orig_upper[i], qlp->upper[i]);
+ EGLPNUM_TYPENAME_EGlpNumOne (minf->downpen[i]);
+ EGLPNUM_TYPENAME_EGlpNumOne (minf->uppen[i]);
+ EGLPNUM_TYPENAME_EGlpNumSign (minf->downpen[i]);
+ EGLPNUM_TYPENAME_EGlpNumSign (minf->uppen[i]);
+ }
+
+
+CLEANUP:
+
+ EGLPNUM_TYPENAME_EGlpNumClearVar (val);
+ ILL_RETURN (rval, "startup_mip");
+}
+
+static void cleanup_mip (
+ mipinfo * minf)
+{
+ int i;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp;
+
+ if (minf && minf->lp)
+ {
+ qslp = minf->lp->O;
+ if (minf->objsense == EGLPNUM_TYPENAME_ILL_MAX)
+ {
+ for (i = 0; i < minf->lp->ncols; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumSign (qslp->obj[i]);
+ }
+ qslp->objsense = EGLPNUM_TYPENAME_ILL_MIN;
+ }
+ }
+}
+
+static int run_bfs (
+ mipinfo * minf,
+ itcnt_t*itcnt)
+{
+ int rval = 0;
+ bbnode *b;
+
+ while (minf->head_bbnode.next)
+ {
+ best_bbnode (minf, &b);
+ rval = process_bfs_bbnode (minf, b, itcnt);
+ ILL_CLEANUP_IF (rval);
+ remove_bbnode (b);
+ free_bbnode (b);
+ bbnodefree (&minf->ptrworld, b);
+ minf->activenodes--;
+ }
+
+CLEANUP:
+
+ ILL_RETURN (rval, "run_bfs");
+}
+
+static int process_bfs_bbnode (
+ mipinfo * minf,
+ bbnode * active,
+ itcnt_t*itcnt)
+{
+ EGLPNUM_TYPENAME_lpinfo *lp = minf->lp;
+ EGLPNUM_TYPENAME_ILLlp_basis B;
+ int status, bvar = 0;
+ int i, j, hit, dnp = 0, upp = 0;
+ int nstruct = lp->O->nstruct;
+ EGLPNUM_TYPE t, lpval, dnval, upval;
+ EGLPNUM_TYPE *wupper = 0;
+ EGLPNUM_TYPE *wlower = 0;
+ int rval = 0;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (t);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (lpval);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (dnval);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (upval);
+
+ EGLPNUM_TYPENAME_ILLlp_basis_init (&B);
+
+ if (minf->watch > 1)
+ {
+ QSlog("Node %4d: %.3f", active->id, EGLPNUM_TYPENAME_EGlpNumToLf (active->bound));
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (minf->value, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+ QSlog(" %.3f", EGLPNUM_TYPENAME_EGlpNumToLf (minf->value));
+ else
+ QSlog(" None");
+ QSlog(", Active %d ", minf->activenodes);
+ }
+ else if (minf->watch == 1)
+ {
+ if (minf->lastpivots > 1000)
+ {
+ minf->lastpivots = 0;
+ QSlog("Pivots %d, Active Nodes %d, Bound %.3f, Soln ",
+ minf->totalpivots, minf->activenodes,
+ EGLPNUM_TYPENAME_EGlpNumToLf (active->bound));
+ if (!EGLPNUM_TYPENAME_EGlpNumIsLess (minf->value, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+ QSlog("%.3f", EGLPNUM_TYPENAME_EGlpNumToLf (minf->value));
+ else
+ QSlog("None");
+ }
+ }
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsLeq (minf->objectivebound, active->bound))
+ {
+ if (minf->watch > 1)
+ {
+ QSlog(" Node can be purged");
+ }
+ goto CLEANUP;
+ }
+
+ /* Set the LP bounds for the node. */
+
+ wlower = EGLPNUM_TYPENAME_EGlpNumAllocArray (nstruct);
+ wupper = EGLPNUM_TYPENAME_EGlpNumAllocArray (nstruct);
+
+ for (i = 0; i < nstruct; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (wlower[i], minf->orig_lower[i]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (wupper[i], minf->orig_upper[i]);
+ }
+ for (i = 0; i < active->bound_cnt; i++)
+ {
+ j = active->bound_indx[i];
+ if (active->lu[i] == 'L')
+ EGLPNUM_TYPENAME_EGlpNumCopy (wlower[j], active->bounds[i]);
+ else
+ EGLPNUM_TYPENAME_EGlpNumCopy (wupper[j], active->bounds[i]);
+ }
+
+ if (active->bound_cnt > 0)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlib_chgbnds (lp, active->bound_cnt, active->bound_indx,
+ active->lu, active->bounds);
+ ILL_CLEANUP_IF (rval);
+ }
+
+ /* Solve the LP. */
+
+ rval = EGLPNUM_TYPENAME_ILLlib_loadbasis (&B, nstruct, lp->nrows, active->cstat,
+ active->rstat);
+ ILL_CLEANUP_IF (rval);
+ if (active->rownorms)
+ {
+ B.rownorms = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+ for (i = 0; i < lp->nrows; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (B.rownorms[i], active->rownorms[i]);
+ }
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLlib_optimize (lp, &B, minf->pinf, DUAL_SIMPLEX, &status, 0, itcnt);
+ ILL_CLEANUP_IF (rval);
+
+ minf->totalpivots += EGLPNUM_TYPENAME_ILLlib_iter (lp);
+ minf->lastpivots += EGLPNUM_TYPENAME_ILLlib_iter (lp);
+
+ if (status == QS_LP_UNSOLVED)
+ {
+ QSlog("Simplex did not solve the LP");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ if (status == QS_LP_INFEASIBLE)
+ {
+ QSlog(" Infeasible LP, should have been purged earlier");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ if (active->depth < 0)
+ {
+ for (i = 0; i < nstruct; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (minf->lower[i], wlower[i]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (minf->upper[i], wupper[i]);
+ }
+ rval = plunge (minf, itcnt);
+ ILL_CLEANUP_IF (rval);
+ }
+
+ /* Fix variables. */
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (minf->value, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+ {
+ rval = fix_variables (lp, &(minf->value), active, wupper, wlower, &hit);
+ ILL_CLEANUP_IF (rval);
+
+ if (hit)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlib_optimize (lp, &B, minf->pinf, DUAL_SIMPLEX, &status, 0, itcnt);
+ ILL_CLEANUP_IF (rval);
+
+ minf->totalpivots += EGLPNUM_TYPENAME_ILLlib_iter (lp);
+ minf->lastpivots += EGLPNUM_TYPENAME_ILLlib_iter (lp);
+
+ if (status == QS_LP_UNSOLVED)
+ {
+ QSlog("Simplex did not solve the LP");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ if (status == QS_LP_INFEASIBLE)
+ {
+ QSlog(" Infeasible LP after fixing");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+ }
+ }
+
+
+ /* Branch. */
+
+ rval = EGLPNUM_TYPENAME_ILLlib_get_x (lp, 0, minf->x);
+ ILL_CLEANUP_IF (rval);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_objval (lp, 0, &lpval);
+ ILL_CLEANUP_IF (rval);
+
+ rval = find_branch (minf, minf->x, &lpval, &bvar, itcnt);
+ ILL_CLEANUP_IF (rval);
+
+ if (bvar == -1)
+ {
+ QSlog("Found integral solution: %f", EGLPNUM_TYPENAME_EGlpNumToLf (lpval));
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (lpval, minf->value))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (minf->value, lpval);
+ EGLPNUM_TYPENAME_EGlpNumCopy (minf->objectivebound, lpval);
+ EGLPNUM_TYPENAME_EGlpNumSubTo (minf->objectivebound, ILL_INTTOL);
+ copy_x (nstruct, minf->x, minf->bestx);
+ }
+ }
+ else
+ {
+ /* Create down child */
+
+ rval = child_work (minf, active, bvar, 'D', &dnval, &dnp, itcnt);
+ ILL_CLEANUP_IF (rval);
+
+ /* Restore parent basis */
+
+ rval = EGLPNUM_TYPENAME_ILLlib_loadbasis (&B, nstruct, lp->nrows, active->cstat,
+ active->rstat);
+ ILL_CLEANUP_IF (rval);
+ if (active->rownorms)
+ {
+ B.rownorms = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+ for (i = 0; i < lp->nrows; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (B.rownorms[i], active->rownorms[i]);
+ }
+ }
+
+ /* Create up child */
+
+ rval = child_work (minf, active, bvar, 'U', &upval, &upp, itcnt);
+ ILL_CLEANUP_IF (rval);
+
+ if (minf->watch > 1)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (dnval, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+ {
+ QSlog("DN->XXX");
+ }
+ else
+ {
+ QSlog("DN->%.3f%c", EGLPNUM_TYPENAME_EGlpNumToLf (dnval), dnp ? 'X' : ' ');
+ }
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (upval, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+ {
+ QSlog("UP->XXX");
+ }
+ else
+ {
+ QSlog("UP->%.3f%c", EGLPNUM_TYPENAME_EGlpNumToLf (upval), upp ? 'X' : ' ');
+ }
+ }
+ }
+
+ /* Set the LP bounds back to original values */
+
+ for (i = 0; i < active->bound_cnt; i++)
+ {
+ if (active->lu[i] == 'L')
+ EGLPNUM_TYPENAME_EGlpNumCopy (t, minf->orig_lower[active->bound_indx[i]]);
+ else
+ EGLPNUM_TYPENAME_EGlpNumCopy (t, minf->orig_upper[active->bound_indx[i]]);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, active->bound_indx[i], active->lu[i], t);
+ ILL_CLEANUP_IF (rval);
+ }
+
+CLEANUP:
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (wlower);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (wupper);
+ EGLPNUM_TYPENAME_ILLlp_basis_free (&B);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (t);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (lpval);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (dnval);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (upval);
+ ILL_RETURN (rval, "process_bfs_bbnode");
+}
+
+static int child_work (
+ mipinfo * minf,
+ bbnode * active,
+ int bvar,
+ int bdir,
+ EGLPNUM_TYPE * cval,
+ int *cp,
+ itcnt_t*itcnt)
+{
+ int tval, rval = 0;
+ int i, status, intsol;
+ EGLPNUM_TYPE t, oldt, lpval;
+ EGLPNUM_TYPE *xi = &(minf->x[bvar]);
+ EGLPNUM_TYPENAME_lpinfo *lp = minf->lp;
+ bbnode *b;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (t);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (lpval);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (oldt);
+
+ *cp = 0;
+
+ if (bdir == 'D')
+ {
+ rval = EGLPNUM_TYPENAME_ILLlib_getbnd (lp, bvar, 'U', &oldt);
+ ILL_CLEANUP_IF (rval);
+ EGLPNUM_TYPENAME_EGlpNumFloor (t, *xi);
+ rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, bvar, 'U', t);
+ ILL_CLEANUP_IF (rval);
+ }
+ else
+ {
+ rval = EGLPNUM_TYPENAME_ILLlib_getbnd (lp, bvar, 'L', &oldt);
+ ILL_CLEANUP_IF (rval);
+ EGLPNUM_TYPENAME_EGlpNumCeil (t, *xi);
+ rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, bvar, 'L', t);
+ ILL_CLEANUP_IF (rval);
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLlib_optimize (lp, 0, minf->pinf, DUAL_SIMPLEX, &status, 0, itcnt);
+ ILL_CLEANUP_IF (rval);
+
+ minf->totalpivots += EGLPNUM_TYPENAME_ILLlib_iter (lp);
+ minf->lastpivots += EGLPNUM_TYPENAME_ILLlib_iter (lp);
+
+ if (status == QS_LP_UNSOLVED)
+ {
+ QSlog("Simplex did not solve Child LP");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ if (status == QS_LP_INFEASIBLE)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (*cval, EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+ *cp = 1;
+ }
+ else
+ {
+ rval = EGLPNUM_TYPENAME_ILLlib_objval (lp, 0, &lpval);
+ ILL_CLEANUP_IF (rval);
+ EGLPNUM_TYPENAME_EGlpNumCopy (*cval, lpval);
+
+ /* What about the x vector? Bico - 020531 */
+
+ check_integral (lp, minf->x, &intsol);
+ if (intsol)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (lpval, minf->value))
+ {
+ QSlog("Found integral solution: %f", EGLPNUM_TYPENAME_EGlpNumToLf (lpval));
+ EGLPNUM_TYPENAME_EGlpNumCopy (minf->value, lpval);
+ EGLPNUM_TYPENAME_EGlpNumCopy (minf->objectivebound, lpval);
+ EGLPNUM_TYPENAME_EGlpNumSubTo (minf->objectivebound, ILL_INTTOL);
+ copy_x (lp->O->nstruct, minf->x, minf->bestx);
+ }
+ }
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsLeq (minf->objectivebound, lpval))
+ {
+ *cp = 1;
+ }
+ else
+ {
+ b = bbnodealloc (&minf->ptrworld);
+ init_bbnode (b);
+ b->depth = active->depth + 1;
+ b->id = minf->totalnodes;
+ EGLPNUM_TYPENAME_EGlpNumCopy (b->bound, lpval);
+ ILL_SAFE_MALLOC (b->cstat, lp->O->nstruct, char);
+ ILL_SAFE_MALLOC (b->rstat, lp->nrows, char);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_getbasis (lp, b->cstat, b->rstat);
+ ILL_CLEANUP_IF (rval);
+ if (minf->pinf->dII_price == QS_PRICE_DSTEEP)
+ {
+ b->rownorms = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+ tval = EGLPNUM_TYPENAME_ILLlib_getrownorms (lp, minf->pinf, b->rownorms);
+ if (tval)
+ {
+ QSlog("Row norms not available");
+ QSlog("A");
+ exit (1);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (b->rownorms);
+ }
+ }
+ ILL_SAFE_MALLOC (b->bound_indx, active->bound_cnt + 1, int);
+ ILL_SAFE_MALLOC (b->lu, active->bound_cnt + 1, char);
+
+ b->bounds = EGLPNUM_TYPENAME_EGlpNumAllocArray (active->bound_cnt + 1);
+ for (i = 0; i < active->bound_cnt; i++)
+ {
+ b->bound_indx[i] = active->bound_indx[i];
+ b->lu[i] = active->lu[i];
+ EGLPNUM_TYPENAME_EGlpNumCopy (b->bounds[i], active->bounds[i]);
+ }
+ b->bound_indx[active->bound_cnt] = bvar;
+ if (bdir == 'D')
+ b->lu[active->bound_cnt] = 'U';
+ else
+ b->lu[active->bound_cnt] = 'L';
+ EGLPNUM_TYPENAME_EGlpNumCopy (b->bounds[active->bound_cnt], t);
+ b->bound_cnt = active->bound_cnt + 1;
+
+ rval = EGLPNUM_TYPENAME_ILLutil_priority_insert (minf->que, (void *) b, &lpval,
+ &(b->handle));
+ ILL_CLEANUP_IF (rval);
+
+ put_bbnode (minf, b);
+ minf->activenodes++;
+ }
+ }
+ minf->totalnodes++;
+
+ if (bdir == 'D')
+ {
+ rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, bvar, 'U', oldt);
+ ILL_CLEANUP_IF (rval);
+ }
+ else
+ {
+ rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, bvar, 'L', oldt);
+ ILL_CLEANUP_IF (rval);
+ }
+
+CLEANUP:
+
+ EGLPNUM_TYPENAME_EGlpNumClearVar (t);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (lpval);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (oldt);
+ return rval;
+}
+
+static int fix_variables (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPE * bestval,
+ bbnode * b,
+ EGLPNUM_TYPE * wupper,
+ EGLPNUM_TYPE * wlower,
+ int *hit)
+{
+ int rval = 0;
+ int i, nnew = 0;
+ int nstruct = lp->O->nstruct;
+ EGLPNUM_TYPE delta, lpval;
+ int *new_indx = 0;
+ char *new_lu = 0;
+ EGLPNUM_TYPE *new_bounds = 0;
+ EGLPNUM_TYPE *dj = 0;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (delta);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (lpval);
+
+ *hit = 0;
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (*bestval, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+ {
+ rval = EGLPNUM_TYPENAME_ILLlib_objval (lp, 0, &lpval);
+ ILL_CLEANUP_IF (rval);
+ //delta = bestval - lpval + ILL_INTTOL;
+ EGLPNUM_TYPENAME_EGlpNumCopy (delta, *bestval);
+ EGLPNUM_TYPENAME_EGlpNumSubTo (delta, lpval);
+ EGLPNUM_TYPENAME_EGlpNumAddTo (delta, ILL_INTTOL);
+
+ ILL_SAFE_MALLOC (new_indx, nstruct, int);
+ ILL_SAFE_MALLOC (new_lu, nstruct, char);
+
+ dj = EGLPNUM_TYPENAME_EGlpNumAllocArray (nstruct);
+ new_bounds = EGLPNUM_TYPENAME_EGlpNumAllocArray (nstruct);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_solution (lp, 0, 0, 0, 0, 0, dj);
+ ILL_CLEANUP_IF (rval);
+
+ for (i = 0; i < nstruct; i++)
+ {
+ if (lp->O->intmarker[i])
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (wlower[i], wupper[i]))
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (delta, dj[i]))
+ {
+ EGLPNUM_TYPENAME_EGlpNumSubTo (wupper[i], EGLPNUM_TYPENAME_oneLpNum);
+ rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, i, 'U', wupper[i]);
+ ILL_CLEANUP_IF (rval);
+ new_indx[nnew] = i;
+ new_lu[nnew] = 'U';
+ EGLPNUM_TYPENAME_EGlpNumCopy (new_bounds[nnew], wupper[i]);
+ nnew++;
+ }
+ /*if (-dj[i] > delta) */
+ EGLPNUM_TYPENAME_EGlpNumSign (delta);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (delta, dj[i]))
+ {
+ EGLPNUM_TYPENAME_EGlpNumAddTo (wlower[i], EGLPNUM_TYPENAME_oneLpNum);
+ rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, i, 'L', wlower[i]);
+ ILL_CLEANUP_IF (rval);
+ new_indx[nnew] = i;
+ new_lu[nnew] = 'L';
+ EGLPNUM_TYPENAME_EGlpNumCopy (new_bounds[nnew], wlower[i]);
+ nnew++;
+ }
+ EGLPNUM_TYPENAME_EGlpNumSign (delta);
+ }
+ }
+ }
+
+ if (nnew)
+ {
+ b->bound_indx =
+ EGrealloc (b->bound_indx, sizeof (int) * (b->bound_cnt + nnew));
+ //rval = ILLutil_reallocrus_count ((void **) &(b->bound_indx),
+ // b->bound_cnt + nnew, sizeof (int));
+ //ILL_CLEANUP_IF (rval);
+ b->lu = EGrealloc (b->lu, sizeof (char) * (b->bound_cnt + nnew));
+ //rval = ILLutil_reallocrus_count ((void **) &(b->lu),
+ // b->bound_cnt + nnew, sizeof (char));
+ //ILL_CLEANUP_IF (rval);
+ EGLPNUM_TYPENAME_EGlpNumReallocArray (&(b->bounds), b->bound_cnt + nnew);
+ for (i = 0; i < nnew; i++)
+ {
+ b->bound_indx[b->bound_cnt + i] = new_indx[i];
+ b->lu[b->bound_cnt + i] = new_lu[i];
+ EGLPNUM_TYPENAME_EGlpNumCopy (b->bounds[b->bound_cnt + i], new_bounds[i]);
+ }
+ b->bound_cnt += nnew;
+ }
+ }
+
+ *hit = nnew;
+
+CLEANUP:
+
+ ILL_IFFREE (new_indx, int);
+ ILL_IFFREE (new_lu, char);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (dj);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (new_bounds);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (delta);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (lpval);
+ return rval;
+}
+
+static void best_bbnode (
+ mipinfo * minf,
+ bbnode ** best)
+{
+#if 0
+ bbnode *b;
+ double bestval = EGLPNUM_TYPENAME_ILL_MAXDOUBLE;
+
+ for (b = minf->head_bbnode.next; b; b = b->next)
+ {
+ if (b->bound < bestval)
+ {
+ *best = b;
+ bestval = b->bound;
+ }
+ }
+#endif
+
+ EGLPNUM_TYPE val;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (val);
+ EGLPNUM_TYPENAME_ILLutil_priority_deletemin (minf->que, &val, (void **) best);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (val);
+}
+
+static void put_bbnode (
+ mipinfo * minf,
+ bbnode * b)
+{
+ b->next = minf->head_bbnode.next;
+ b->prev = &(minf->head_bbnode);
+ if (b->next)
+ b->next->prev = b;
+ minf->head_bbnode.next = b;
+}
+
+static void remove_bbnode (
+ bbnode * b)
+{
+ b->prev->next = b->next;
+ if (b->next)
+ b->next->prev = b->prev;
+}
+
+static int find_branch (
+ mipinfo * minf,
+ EGLPNUM_TYPE * x,
+ EGLPNUM_TYPE * lpval,
+ int *bvar,
+ itcnt_t*itcnt)
+{
+ EGLPNUM_TYPENAME_lpinfo *lp = minf->lp;
+ int rval = 0;
+
+ switch (minf->branching_rule)
+ {
+ case PENALTYBRANCH:
+ rval = find_penalty_branch (lp, minf->pinf, x, minf->downpen,
+ minf->uppen, lpval, bvar, itcnt);
+ ILL_CLEANUP_IF (rval);
+ break;
+ case FIRSTBRANCH:
+ find_first_branch (lp, x, bvar);
+ break;
+ case MIDDLEBRANCH:
+ find_middle_branch (lp, x, bvar);
+ break;
+ case STRONGBRANCH:
+ rval = find_strong_branch (lp, minf->pinf, x, bvar, itcnt);
+ ILL_CLEANUP_IF (rval);
+ break;
+ default:
+ QSlog("Unknown branching rule.");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+CLEANUP:
+
+ ILL_RETURN (rval, "find_branch");
+}
+
+static void find_first_branch (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPE * x,
+ int *bvar)
+{
+ int i, ibest = -1;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp = lp->O;
+ EGLPNUM_TYPE t;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (t);
+
+ for (i = 0; i < qslp->nstruct; i++)
+ {
+ if (qslp->intmarker[i])
+ {
+ /*t = EGLPNUM_TYPENAME_ILLutil_our_frac (x[i]); */
+ EGLPNUM_TYPENAME_EGlpNumFloor (t, x[i]);
+ EGLPNUM_TYPENAME_EGlpNumSubTo (t, x[i]);
+ EGLPNUM_TYPENAME_EGlpNumSign (t);
+ if ((EGLPNUM_TYPENAME_EGlpNumIsNeqZero (t, ILL_INTTOL)) &&
+ (EGLPNUM_TYPENAME_EGlpNumIsNeq (t, EGLPNUM_TYPENAME_oneLpNum, ILL_INTTOL)))
+ {
+ ibest = i;
+ break;
+ }
+ }
+ }
+ *bvar = ibest;
+ EGLPNUM_TYPENAME_EGlpNumClearVar (t);
+}
+
+static void find_middle_branch (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPE * x,
+ int *bvar)
+{
+ int i, ibest = -1;
+ EGLPNUM_TYPE t, tbest;
+ EGLPNUM_TYPENAME_ILLlpdata *qlp = lp->O;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (t);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (tbest);
+ EGLPNUM_TYPENAME_EGlpNumSet (tbest, 0.5);
+
+ for (i = 0; i < qlp->nstruct; i++)
+ {
+ if (qlp->intmarker[i])
+ {
+ /*t = EGLPNUM_TYPENAME_ILLutil_our_frac (x[i]) - 0.5;
+ * if (t < 0.0)
+ * t = -t; */
+ EGLPNUM_TYPENAME_EGlpNumFloor (t, x[i]);
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (t, 2);
+ EGLPNUM_TYPENAME_EGlpNumSubTo (t, EGLPNUM_TYPENAME_oneLpNum);
+ EGLPNUM_TYPENAME_EGlpNumDivUiTo (t, 2);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (t))
+ EGLPNUM_TYPENAME_EGlpNumSign (t);
+ /*if (t < tbest) */
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (t, tbest))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (tbest, t);
+ ibest = i;
+ }
+ }
+ }
+
+ /*if (tbest < (0.5 - ILL_INTTOL)) */
+ EGLPNUM_TYPENAME_EGlpNumAddTo (tbest, ILL_INTTOL);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessDbl (tbest, 0.5))
+ {
+ *bvar = ibest;
+ }
+ else
+ {
+ *bvar = -1;
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (t);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (tbest);
+}
+
+static int find_penalty_branch (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * pinf,
+ EGLPNUM_TYPE * x,
+ EGLPNUM_TYPE * downpen,
+ EGLPNUM_TYPE * uppen,
+ EGLPNUM_TYPE * lpval,
+ int *bvar,
+ itcnt_t*itcnt)
+{
+ int rval = 0;
+ int i, k, ibest = -1, ncand = 0, nneed = 0;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp = lp->O;
+ int *candidatelist = 0;
+ int *needlist = 0;
+ EGLPNUM_TYPE *fval = 0;
+ EGLPNUM_TYPE *xlist = 0;
+ EGLPNUM_TYPE *newdown = 0;
+ EGLPNUM_TYPE *newup = 0;
+ EGLPNUM_TYPE a, t, tbest;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (a);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (t);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (tbest);
+ EGLPNUM_TYPENAME_EGlpNumCopy (tbest, EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+
+ ILL_SAFE_MALLOC (candidatelist, qslp->nstruct, int);
+ ILL_SAFE_MALLOC (needlist, qslp->nstruct, int);
+
+ fval = EGLPNUM_TYPENAME_EGlpNumAllocArray (qslp->nstruct);
+ xlist = EGLPNUM_TYPENAME_EGlpNumAllocArray (qslp->nstruct);
+ for (i = 0; i < qslp->nstruct; i++)
+ {
+ if (qslp->intmarker[i])
+ {
+ /*fval[i] = x[i] - floor(x[i]); */
+ EGLPNUM_TYPENAME_EGlpNumFloor (fval[i], x[i]);
+ EGLPNUM_TYPENAME_EGlpNumSubTo (fval[i], x[i]);
+ EGLPNUM_TYPENAME_EGlpNumSign (fval[i]);
+ if ((EGLPNUM_TYPENAME_EGlpNumIsNeqZero (fval[i], ILL_INTTOL)) &&
+ (EGLPNUM_TYPENAME_EGlpNumIsNeq (fval[i], EGLPNUM_TYPENAME_oneLpNum, ILL_INTTOL)))
+ {
+ candidatelist[ncand++] = i;
+ /*if (downpen[i] == -1.0) */
+ EGLPNUM_TYPENAME_EGlpNumSign (downpen[i]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (downpen[i], EGLPNUM_TYPENAME_oneLpNum))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (xlist[nneed], x[i]);
+ needlist[nneed++] = i;
+ }
+ EGLPNUM_TYPENAME_EGlpNumSign (downpen[i]);
+ }
+ }
+ }
+
+ if (nneed > 0)
+ {
+ newdown = EGLPNUM_TYPENAME_EGlpNumAllocArray (nneed);
+ newup = EGLPNUM_TYPENAME_EGlpNumAllocArray (nneed);
+ rval = EGLPNUM_TYPENAME_ILLlib_strongbranch (lp, pinf, needlist, nneed,
+ 0, newdown, newup,
+ 5 * STRONG_PIVOTS, EGLPNUM_TYPENAME_ILL_MAXDOUBLE, itcnt);
+ ILL_CLEANUP_IF (rval);
+
+ for (i = 0; i < nneed; i++)
+ {
+ k = needlist[i];
+ /*uppen[k] = (newup[i] - lpval) / (1.0 - fval[k]); */
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (uppen[k], newup[i], *lpval);
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (downpen[k], EGLPNUM_TYPENAME_oneLpNum, fval[k]);
+ EGLPNUM_TYPENAME_EGlpNumDivTo (uppen[k], downpen[k]);
+ /*downpen[k] = (newdown[i] - lpval) / fval[k]; */
+ EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (downpen[k], newdown[i], *lpval, fval[k]);
+
+ }
+ }
+
+ for (i = 0; i < ncand; i++)
+ {
+ k = candidatelist[i];
+ /*t = ILL_BRANCH_PENALTY_VAL (downpen[k], uppen[k], fval[k]); */
+ EGLPNUM_TYPENAME_EGlpNumCopy (t, downpen[k]);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (t, fval[k]);
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (a, EGLPNUM_TYPENAME_oneLpNum, fval[k]);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (a, uppen[k]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (t, a))
+ {
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (t, ILL_BRANCH_PENALTY_WEIGHT);
+ EGLPNUM_TYPENAME_EGlpNumAddTo (t, a);
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (a, ILL_BRANCH_PENALTY_WEIGHT);
+ EGLPNUM_TYPENAME_EGlpNumAddTo (t, a);
+ }
+ EGLPNUM_TYPENAME_EGlpNumDivUiTo (t, ILL_BRANCH_PENALTY_WEIGHT + 1);
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (tbest, t))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (tbest, t);
+ ibest = k;
+ }
+ }
+
+ *bvar = ibest;
+
+CLEANUP:
+
+ EGLPNUM_TYPENAME_EGlpNumClearVar (a);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (t);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (tbest);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (newdown);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (newup);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (fval);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (xlist);
+ ILL_IFFREE (candidatelist, int);
+ ILL_IFFREE (needlist, int);
+
+ return rval;
+}
+
+static int find_strong_branch (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * pinf,
+ EGLPNUM_TYPE * x,
+ int *bvar,
+ itcnt_t*itcnt)
+{
+ int rval = 0;
+ int i, ibest = -1, ncand = 0;
+ int maxtrys = STRONG_CANDIDATES;
+ EGLPNUM_TYPE t, tbest;
+ EGLPNUM_TYPENAME_ILLlpdata *qlp = lp->O;
+ int *candidatelist = 0;
+ int *newlist = 0;
+ int *perm = 0;
+ EGLPNUM_TYPE *tval = 0;
+ EGLPNUM_TYPE *xlist = 0;
+ EGLPNUM_TYPE *downpen = 0;
+ EGLPNUM_TYPE *uppen = 0;
+ ILLrandstate rstate;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (t);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (tbest);
+ EGLPNUM_TYPENAME_EGlpNumCopy (tbest, EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+
+ ILLutil_sprand (999, &rstate);
+ ILL_SAFE_MALLOC (candidatelist, qlp->nstruct, int);
+
+ tval = EGLPNUM_TYPENAME_EGlpNumAllocArray (qlp->nstruct);
+
+ for (i = 0; i < qlp->nstruct; i++)
+ {
+ if (qlp->intmarker[i])
+ {
+ /*t = EGLPNUM_TYPENAME_ILLutil_our_frac (x[i]) - 0.5;
+ * if (t < 0.0)
+ * t = -t; */
+ EGLPNUM_TYPENAME_EGlpNumFloor (t, x[i]);
+ EGLPNUM_TYPENAME_EGlpNumSubTo (t, x[i]);
+ EGLPNUM_TYPENAME_EGlpNumSign (t);
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (t, 2);
+ EGLPNUM_TYPENAME_EGlpNumSubTo (t, EGLPNUM_TYPENAME_oneLpNum);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (t))
+ EGLPNUM_TYPENAME_EGlpNumSign (t);
+ /*if (t < (0.5 - ILL_INTTOL)) */
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeq (t, EGLPNUM_TYPENAME_oneLpNum, ILL_INTTOL))
+ {
+ candidatelist[ncand] = i;
+ EGLPNUM_TYPENAME_EGlpNumDivUiTo (t, 2);
+ EGLPNUM_TYPENAME_EGlpNumCopy (tval[ncand++], t);
+ }
+ }
+ }
+
+ if (ncand > 0)
+ {
+ if (ncand > maxtrys)
+ {
+ ILL_SAFE_MALLOC (perm, ncand, int);
+
+ for (i = 0; i < ncand; i++)
+ {
+ perm[i] = i;
+ }
+ EGLPNUM_TYPENAME_ILLutil_EGlpNum_rselect (perm, 0, ncand - 1, maxtrys, tval, &rstate);
+
+ ILL_SAFE_MALLOC (newlist, maxtrys, int);
+
+ for (i = 0; i < maxtrys; i++)
+ {
+ newlist[i] = candidatelist[perm[i]];
+ }
+ ILL_IFFREE (candidatelist, int);
+
+ candidatelist = newlist;
+ newlist = 0;
+ ncand = maxtrys;
+ }
+
+ downpen = EGLPNUM_TYPENAME_EGlpNumAllocArray (ncand);
+ uppen = EGLPNUM_TYPENAME_EGlpNumAllocArray (ncand);
+ xlist = EGLPNUM_TYPENAME_EGlpNumAllocArray (ncand);
+
+ for (i = 0; i < ncand; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (xlist[i], x[candidatelist[i]]);
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLlib_strongbranch (lp, pinf, candidatelist, ncand,
+ 0, downpen, uppen, STRONG_PIVOTS,
+ EGLPNUM_TYPENAME_ILL_MAXDOUBLE, itcnt);
+ ILL_CLEANUP_IF (rval);
+
+ for (i = 0; i < ncand; i++)
+ {
+ /*t = ILL_BRANCH_STRONG_VAL (downpen[i], uppen[i]); */
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (downpen[i], uppen[i]))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (t, downpen[i]);
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (t, ILL_BRANCH_STRONG_WEIGHT);
+ EGLPNUM_TYPENAME_EGlpNumAddTo (t, uppen[i]);
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (t, uppen[i]);
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (t, ILL_BRANCH_STRONG_WEIGHT);
+ EGLPNUM_TYPENAME_EGlpNumAddTo (t, downpen[i]);
+ }
+ EGLPNUM_TYPENAME_EGlpNumDivUiTo (t, ILL_BRANCH_STRONG_WEIGHT + 1);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (tbest, t))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (tbest, t);
+ ibest = candidatelist[i];
+ }
+ }
+ }
+
+ *bvar = ibest;
+
+
+CLEANUP:
+
+ EGLPNUM_TYPENAME_EGlpNumClearVar (t);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (tbest);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (tval);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (xlist);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (uppen);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (downpen);
+ ILL_IFFREE (candidatelist, int);
+ ILL_IFFREE (newlist, int);
+ ILL_IFFREE (perm, int);
+
+ ILL_RETURN (rval, "find_strong_branch");
+}
+
+static void check_integral (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPE * x,
+ int *yesno)
+{
+ int i;
+ EGLPNUM_TYPE t;
+ EGLPNUM_TYPENAME_ILLlpdata *qlp = lp->O;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (t);
+
+ for (i = 0; i < qlp->nstruct; i++)
+ {
+ if (qlp->intmarker[i])
+ {
+ /*t = EGLPNUM_TYPENAME_ILLutil_our_frac (x[i]); */
+ EGLPNUM_TYPENAME_EGlpNumFloor (t, x[i]);
+ EGLPNUM_TYPENAME_EGlpNumSubTo (t, x[i]);
+ EGLPNUM_TYPENAME_EGlpNumSign (t);
+ /*if (t > ILL_INTTOL && t < 1.0 - ILL_INTTOL) */
+ if ((EGLPNUM_TYPENAME_EGlpNumIsNeqZero (t, ILL_INTTOL)) &&
+ (EGLPNUM_TYPENAME_EGlpNumIsNeq (t, EGLPNUM_TYPENAME_oneLpNum, ILL_INTTOL)))
+ {
+ *yesno = 0;
+ EGLPNUM_TYPENAME_EGlpNumClearVar (t);
+ return;
+ }
+ }
+ }
+
+ *yesno = 1;
+ EGLPNUM_TYPENAME_EGlpNumClearVar (t);
+}
+
+static int plunge (
+ mipinfo * minf,
+ itcnt_t*itcnt)
+{
+ int rval = 0;
+ int i, status;
+ EGLPNUM_TYPENAME_lpinfo *lp = minf->lp;
+ EGLPNUM_TYPENAME_ILLlpdata *qlp = minf->lp->O;
+ EGLPNUM_TYPE *oldlower = 0;
+ EGLPNUM_TYPE *oldupper = 0;
+
+ if (minf->watch)
+ {
+ QSlog("Plunging ...");
+ }
+
+ oldlower = EGLPNUM_TYPENAME_EGlpNumAllocArray (qlp->nstruct);
+ oldupper = EGLPNUM_TYPENAME_EGlpNumAllocArray (qlp->nstruct);
+
+ for (i = 0; i < qlp->nstruct; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (oldlower[i], minf->lower[i]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (oldupper[i], minf->upper[i]);
+ }
+
+ rval = plunge_work (minf, 0, itcnt);
+ ILL_CLEANUP_IF (rval);
+
+ for (i = 0; i < qlp->nstruct; i++)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, i, 'L', oldlower[i]);
+ ILL_CLEANUP_IF (rval);
+ rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, i, 'U', oldupper[i]);
+ ILL_CLEANUP_IF (rval);
+ EGLPNUM_TYPENAME_EGlpNumCopy (minf->lower[i], oldlower[i]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (minf->upper[i], oldupper[i]);
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLlib_optimize (lp, 0, minf->pinf, DUAL_SIMPLEX, &status, 0, itcnt);
+ ILL_CLEANUP_IF (rval);
+
+
+CLEANUP:
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (oldlower);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (oldupper);
+
+ ILL_RETURN (rval, "plunge");
+}
+
+static int plunge_work (
+ mipinfo * minf,
+ int depth,
+ itcnt_t*itcnt)
+{
+ int rval = 0;
+ int bvar, status, count;
+ EGLPNUM_TYPE lpval, val0, val1, int_tol;
+ EGLPNUM_TYPENAME_lpinfo *lp = minf->lp;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (lpval);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (val0);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (val1);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (int_tol);
+ EGLPNUM_TYPENAME_EGlpNumSet (int_tol, 0.001);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_get_x (lp, 0, minf->x);
+ ILL_CLEANUP_IF (rval);
+
+ rval = round_variables (minf, &count, &int_tol /* 0.001 */ );
+ ILL_CLEANUP_IF (rval);
+ if (count)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlib_optimize (lp, 0, minf->pinf, DUAL_SIMPLEX, &status, 0, itcnt);
+ ILL_CLEANUP_IF (rval);
+ if (status != QS_LP_OPTIMAL)
+ {
+ goto CLEANUP;
+ }
+ rval = EGLPNUM_TYPENAME_ILLlib_get_x (lp, 0, minf->x);
+ ILL_CLEANUP_IF (rval);
+ }
+
+ find_middle_branch (lp, minf->x, &bvar);
+ if (bvar == -1)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlib_objval (lp, 0, &lpval);
+ ILL_CLEANUP_IF (rval);
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (lpval, minf->value))
+ {
+ QSlog("Plunge Integral Solution: %.6f (Depth: %d)",
+ EGLPNUM_TYPENAME_EGlpNumToLf (lpval), depth);
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (minf->value, lpval);
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (minf->objectivebound, lpval, ILL_INTTOL);
+ copy_x (lp->O->nstruct, minf->x, minf->bestx);
+ }
+ goto CLEANUP;
+ }
+
+ EGLPNUM_TYPENAME_EGlpNumOne (minf->lower[bvar]);
+ rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, bvar, 'L', EGLPNUM_TYPENAME_oneLpNum);
+ ILL_CLEANUP_IF (rval);
+ rval = EGLPNUM_TYPENAME_ILLlib_optimize (lp, 0, minf->pinf, DUAL_SIMPLEX, &status, 0, itcnt);
+ ILL_CLEANUP_IF (rval);
+
+ if (status == QS_LP_UNSOLVED)
+ {
+ QSlog("Simplex did not solve the plunge LP");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+ else if (status == QS_LP_INFEASIBLE)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (val1, EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+ }
+ else if (status == QS_LP_OPTIMAL)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlib_objval (lp, 0, &val1);
+ ILL_CLEANUP_IF (rval);
+ }
+ else
+ {
+ ILL_CLEANUP;
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, bvar, 'L', EGLPNUM_TYPENAME_zeroLpNum);
+ ILL_CLEANUP_IF (rval);
+ EGLPNUM_TYPENAME_EGlpNumZero (minf->lower[bvar]);
+
+ EGLPNUM_TYPENAME_EGlpNumZero (minf->upper[bvar]);
+ rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, bvar, 'U', EGLPNUM_TYPENAME_zeroLpNum);
+ ILL_CLEANUP_IF (rval);
+ rval = EGLPNUM_TYPENAME_ILLlib_optimize (lp, 0, minf->pinf, DUAL_SIMPLEX, &status, 0, itcnt);
+ ILL_CLEANUP_IF (rval);
+
+ if (status == QS_LP_UNSOLVED)
+ {
+ QSlog("Simplex did not solve the plunge LP");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+ else if (status == QS_LP_INFEASIBLE)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (val0, EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+ }
+ else if (status == QS_LP_OPTIMAL)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlib_objval (lp, 0, &val0);
+ ILL_CLEANUP_IF (rval);
+ }
+ else
+ {
+ ILL_CLEANUP;
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, bvar, 'U', EGLPNUM_TYPENAME_oneLpNum);
+ ILL_CLEANUP_IF (rval);
+ EGLPNUM_TYPENAME_EGlpNumCopy (minf->upper[bvar], EGLPNUM_TYPENAME_oneLpNum);
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (val0, EGLPNUM_TYPENAME_ILL_MAXDOUBLE) &&
+ EGLPNUM_TYPENAME_EGlpNumIsEqqual (val1, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+ {
+ ILL_CLEANUP;
+ }
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (val0, val1))
+ {
+ EGLPNUM_TYPENAME_EGlpNumZero (minf->upper[bvar]);
+ rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, bvar, 'U', EGLPNUM_TYPENAME_zeroLpNum);
+ ILL_CLEANUP_IF (rval);
+ rval = EGLPNUM_TYPENAME_ILLlib_optimize (lp, 0, minf->pinf, DUAL_SIMPLEX, &status, 0, itcnt);
+ ILL_CLEANUP_IF (rval);
+ rval = plunge_work (minf, depth + 1, itcnt);
+ ILL_CLEANUP_IF (rval);
+ rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, bvar, 'U', EGLPNUM_TYPENAME_oneLpNum);
+ ILL_CLEANUP_IF (rval);
+ EGLPNUM_TYPENAME_EGlpNumOne (minf->upper[bvar]);
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumOne (minf->lower[bvar]);
+ rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, bvar, 'L', EGLPNUM_TYPENAME_oneLpNum);
+ ILL_CLEANUP_IF (rval);
+ rval = EGLPNUM_TYPENAME_ILLlib_optimize (lp, 0, minf->pinf, DUAL_SIMPLEX, &status, 0, itcnt);
+ ILL_CLEANUP_IF (rval);
+ rval = plunge_work (minf, depth + 1, itcnt);
+ ILL_CLEANUP_IF (rval);
+ rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, bvar, 'L', EGLPNUM_TYPENAME_zeroLpNum);
+ ILL_CLEANUP_IF (rval);
+ EGLPNUM_TYPENAME_EGlpNumZero (minf->lower[bvar]);
+ }
+
+CLEANUP:
+
+ EGLPNUM_TYPENAME_EGlpNumClearVar (lpval);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (val0);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (val1);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (int_tol);
+ ILL_RETURN (rval, "plunge_work");
+}
+
+static int round_variables (
+ mipinfo * minf,
+ int *count,
+ EGLPNUM_TYPE * tol)
+{
+ int rval = 0;
+ int i, hit = 0;
+ EGLPNUM_TYPENAME_lpinfo *lp = minf->lp;
+ EGLPNUM_TYPENAME_ILLlpdata *qlp = lp->O;
+
+ *count = 0;
+
+ for (i = 0; i < qlp->nstruct; i++)
+ {
+ if (qlp->intmarker[i])
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (minf->lower[i], minf->upper[i]))
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (minf->x[i], *tol))
+ {
+ EGLPNUM_TYPENAME_EGlpNumZero (minf->upper[i]);
+ rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, i, 'U', EGLPNUM_TYPENAME_zeroLpNum);
+ ILL_CLEANUP_IF (rval);
+ hit++;
+ }
+ else if (EGLPNUM_TYPENAME_EGlpNumIsEqual (minf->x[i], EGLPNUM_TYPENAME_oneLpNum, *tol))
+ {
+ EGLPNUM_TYPENAME_EGlpNumOne (minf->lower[i]);
+ rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, i, 'L', EGLPNUM_TYPENAME_oneLpNum);
+ ILL_CLEANUP_IF (rval);
+ hit++;
+ }
+ }
+ }
+ }
+ *count = hit;
+
+CLEANUP:
+
+ ILL_RETURN (rval, "round_variables");
+}
+
+static void copy_x (
+ int nstruct,
+ EGLPNUM_TYPE * from_x,
+ EGLPNUM_TYPE * to_x)
+{
+ int j;
+
+ for (j = 0; j < nstruct; j++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (to_x[j], from_x[j]);
+ }
+}
+
+static void init_mipinfo (
+ mipinfo * minf)
+{
+ if (minf)
+ {
+ minf->depth = 0;
+ minf->totalnodes = 0;
+ minf->activenodes = 0;
+ minf->totalpivots = 0;
+ minf->lastpivots = 0;
+ minf->downpen = 0;
+ minf->uppen = 0;
+ minf->x = 0;
+ minf->bestx = 0;
+ minf->lower = 0;
+ minf->upper = 0;
+ minf->lp = 0;
+ minf->pinf = 0;
+ minf->head_bbnode.prev = 0;
+ minf->head_bbnode.next = 0;
+ minf->que = 0;
+ minf->branching_rule = /* MIDDLEBRANCH */ STRONGBRANCH;
+ minf->watch = 1;
+ EGLPNUM_TYPENAME_EGlpNumInitVar (minf->objectivebound);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (minf->value);
+ EGLPNUM_TYPENAME_EGlpNumCopy (minf->objectivebound, EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+ EGLPNUM_TYPENAME_EGlpNumCopy (minf->value, EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+ ILLptrworld_init (&minf->ptrworld);
+ }
+}
+
+static void free_mipinfo (
+ mipinfo * minf)
+{
+ int total, onlist;
+
+ if (minf)
+ {
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (minf->downpen);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (minf->uppen);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (minf->x);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (minf->bestx);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (minf->lower);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (minf->upper);
+ bbnode_listfree (&minf->ptrworld, minf->head_bbnode.next);
+ if (bbnode_check_leaks (&minf->ptrworld, &total, &onlist))
+ {
+ QSlog("WARNING: %d outstanding bbnodes", total - onlist);
+ }
+ ILLptrworld_delete (&minf->ptrworld);
+ EGLPNUM_TYPENAME_EGlpNumClearVar ((minf->objectivebound));
+ EGLPNUM_TYPENAME_EGlpNumClearVar ((minf->value));
+ memset (minf, 0, sizeof (mipinfo));
+ //init_mipinfo (minf);
+ }
+}
+
+static void init_bbnode (
+ bbnode * b)
+{
+ if (b)
+ {
+ b->next = 0;
+ b->prev = 0;
+ b->id = 0;
+ b->depth = 0;
+ b->handle = 0;
+ b->cstat = 0;
+ b->rstat = 0;
+ b->rownorms = 0;
+ b->bound_cnt = 0;
+ b->bound_indx = 0;
+ b->lu = 0;
+ b->bounds = 0;
+ EGLPNUM_TYPENAME_EGlpNumInitVar ((b->bound));
+ EGLPNUM_TYPENAME_EGlpNumCopy (b->bound, EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+ }
+}
+
+static void free_bbnode (
+ bbnode * b)
+{
+ if (b)
+ {
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (b->rownorms);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (b->bounds);
+ ILL_IFFREE (b->cstat, char);
+ ILL_IFFREE (b->rstat, char);
+ ILL_IFFREE (b->bound_indx, int);
+ ILL_IFFREE (b->lu, char);
+
+ EGLPNUM_TYPENAME_EGlpNumClearVar ((b->bound));
+ memset (b, 0, sizeof (bbnode));
+ }
+}
diff --git a/qsopt_ex/binary.h b/qsopt_ex/binary.h
new file mode 100644
index 0000000..b859e33
--- /dev/null
+++ b/qsopt_ex/binary.h
@@ -0,0 +1,36 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCSINFO $Id: binary_EGLPNUM_TYPENAME.h,v 1.3 2003/11/05 16:57:39 meven Exp $ */
+/****************************************************************************/
+/* */
+/* binary.c */
+/* */
+/****************************************************************************/
+
+struct itcnt_t;
+
+int EGLPNUM_TYPENAME_ILLmip_bfs (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPE * val,
+ EGLPNUM_TYPE * x,
+ struct itcnt_t*itcnt);
diff --git a/qsopt_ex/dheaps_i.c b/qsopt_ex/dheaps_i.c
new file mode 100644
index 0000000..fcc944d
--- /dev/null
+++ b/qsopt_ex/dheaps_i.c
@@ -0,0 +1,347 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCSINFO $Id: dheaps_i.c,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+/****************************************************************************/
+/* */
+/* This file is part of CONCORDE */
+/* */
+/* (c) Copyright 1995--1999 by David Applegate, Robert Bixby, */
+/* Vasek Chvatal, and William Cook */
+/* */
+/* Permission is granted for academic research use. For other uses, */
+/* contact the authors for licensing options. */
+/* */
+/* Use at your own risk. We make no guarantees about the */
+/* correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* DHEAP ROUTINES */
+/* */
+/* */
+/* TSP CODE */
+/* Written by: Applegate, Bixby, Chvatal, and Cook */
+/* Date: February 9, 1995 */
+/* March 11, 2002 - Cook (Modifed for QS) */
+/* Reference: R.E. Tarjan, Data Structures and Network Algorithms */
+/* */
+/* EXPORTED FUNCTIONS: */
+/* */
+/* int EGLPNUM_TYPENAME_ILLutil_dheap_init (EGLPNUM_TYPENAME_ILLdheap *h, int k) */
+/* -h should point to a EGLPNUM_TYPENAME_ILLdheap struct. */
+/* -k the max number of elements in the dheap. */
+/* */
+/* void EGLPNUM_TYPENAME_ILLutil_dheap_free (EGLPNUM_TYPENAME_ILLdheap *h) */
+/* -frees the spaces allocated by EGLPNUM_TYPENAME_ILLutil_dheap_init */
+/* */
+/* int EGLPNUM_TYPENAME_ILLutil_dheap_resize (EGLPNUM_TYPENAME_ILLdheap *h, int newsize) */
+/* -REALLOCs h so it can contain newsize elements. */
+/* -returns -1 if it can't resize the EGLPNUM_TYPENAME_heap. */
+/* */
+/* void EGLPNUM_TYPENAME_ILLutil_dheap_findmin (EGLPNUM_TYPENAME_ILLdheap *h, int *i) */
+/* -sets i to the index of the element with min value h->key[i] */
+/* -sets i to -1 if no elements in EGLPNUM_TYPENAME_heap. */
+/* */
+/* int EGLPNUM_TYPENAME_ILLutil_dheap_insert (EGLPNUM_TYPENAME_ILLdheap *h, int i) */
+/* -inserts the element with index i (so its key should be loaded */
+/* beforehand in h->key[i]). */
+/* */
+/* void EGLPNUM_TYPENAME_ILLutil_dheap_delete (EGLPNUM_TYPENAME_ILLdheap *h, int i) */
+/* -deletes the element with index i. */
+/* */
+/* void EGLPNUM_TYPENAME_ILLutil_dheap_deletemin (EGLPNUM_TYPENAME_ILLdheap *h, int *i) */
+/* -sets i to the min element in the EGLPNUM_TYPENAME_heap, and deletes the min element */
+/* -sets i to -1 if no elements in EGLPNUM_TYPENAME_heap. */
+/* */
+/* void EGLPNUM_TYPENAME_ILLutil_dheap_changekey (EGLPNUM_TYPENAME_ILLdheap *h, int i, EGLPNUM_TYPE* newkey) */
+/* -changes the key of the element with index i to newkey. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* NOTES: */
+/* A k-element EGLPNUM_TYPENAME_heap will malloc 16k bytes of memory. If memory is */
+/* tight, using integer keys (instead of doubles), brings it down to */
+/* 12k bytes, and if arbitrary deletions are not required, with a little */
+/* rewriting, the h->loc field can be eliminated, bring the space down */
+/* to 8k bytes. */
+/* These routines work with indices into the h->key array, so in */
+/* some cases, you will need to maintain a separate names array to know */
+/* what element belongs to index i. For an example, see the k_nearest */
+/* code in kdnear.c. */
+/* */
+/****************************************************************************/
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "dheaps_i_EGLPNUM_TYPENAME.h"
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "eg_lpnum.h"
+
+#include "allocrus.h"
+#include "except.h"
+#include "trace.h"
+
+static int TRACE = 0;
+
+#define HEAP_D 3
+#define HEAP_UP(x) (((x)-1)/HEAP_D)
+#define HEAP_DOWN(x) (((x)*HEAP_D)+1)
+
+
+static void dheap_siftup (
+ EGLPNUM_TYPENAME_ILLdheap * h,
+ int i,
+ int x),
+ dheap_siftdown (
+ EGLPNUM_TYPENAME_ILLdheap * h,
+ int i,
+ int x);
+
+static int dheap_minchild (
+ int x,
+ EGLPNUM_TYPENAME_ILLdheap * h);
+
+
+int EGLPNUM_TYPENAME_ILLutil_dheap_init (
+ EGLPNUM_TYPENAME_ILLdheap * h,
+ int k)
+{
+ int rval = 0;
+
+ h->entry = (int *) NULL;
+ h->loc = (int *) NULL;
+ h->key = 0;
+
+
+ ILL_SAFE_MALLOC (h->entry, k, int);
+ ILL_SAFE_MALLOC (h->loc, k, int);
+
+ h->key = EGLPNUM_TYPENAME_EGlpNumAllocArray (k);
+ h->size = 0;
+ h->total_space = k;
+
+CLEANUP:
+
+ if (rval)
+ {
+ EGLPNUM_TYPENAME_ILLutil_dheap_free (h);
+ }
+
+ ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLutil_dheap_init");
+}
+
+void EGLPNUM_TYPENAME_ILLutil_dheap_free (
+ EGLPNUM_TYPENAME_ILLdheap * h)
+{
+ ILL_IFFREE (h->entry, int);
+ ILL_IFFREE (h->loc, int);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (h->key);
+}
+
+int EGLPNUM_TYPENAME_ILLutil_dheap_resize (
+ EGLPNUM_TYPENAME_ILLdheap * h,
+ int newsize)
+{
+ int rval = 0;
+
+ if (newsize < h->size || newsize < h->total_space)
+ {
+ ILL_CLEANUP;
+ }
+
+ h->key = EGrealloc (h->key, sizeof (double) * newsize);
+ //rval = ILLutil_reallocrus_count ((void **) &(h->key), newsize,
+ // sizeof (double));
+ //ILL_CLEANUP_IF (rval);
+ h->entry = EGrealloc (h->entry, sizeof (int) * newsize);
+ //rval = ILLutil_reallocrus_count ((void **) &(h->entry), newsize,
+ // sizeof (int));
+ //ILL_CLEANUP_IF (rval);
+ h->loc = EGrealloc (h->loc, sizeof (int) * newsize);
+ //rval = ILLutil_reallocrus_count ((void **) &(h->loc), newsize, sizeof (int));
+ //ILL_CLEANUP_IF (rval);
+ h->total_space = newsize;
+
+CLEANUP:
+
+ ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLutil_dheap_resize");
+}
+
+void EGLPNUM_TYPENAME_ILLutil_dheap_findmin (
+ EGLPNUM_TYPENAME_ILLdheap * h,
+ int *i)
+{
+ if (h->size == 0)
+ *i = -1;
+ else
+ *i = h->entry[0];
+}
+
+int EGLPNUM_TYPENAME_ILLutil_dheap_insert (
+ EGLPNUM_TYPENAME_ILLdheap * h,
+ int i)
+{
+ if (h->size >= h->total_space)
+ {
+ QSlog("Error - EGLPNUM_TYPENAME_heap already full");
+ return 1;
+ }
+ h->size++;
+ dheap_siftup (h, i, h->size - 1);
+
+ return 0;
+}
+
+void EGLPNUM_TYPENAME_ILLutil_dheap_delete (
+ EGLPNUM_TYPENAME_ILLdheap * h,
+ int i)
+{
+ int j;
+
+ h->size--;
+ j = h->entry[h->size];
+ h->entry[h->size] = -1;
+
+ if (j != i)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsLeq (h->key[j], h->key[i]))
+ {
+ dheap_siftup (h, j, h->loc[i]);
+ }
+ else
+ {
+ dheap_siftdown (h, j, h->loc[i]);
+ }
+ }
+}
+
+void EGLPNUM_TYPENAME_ILLutil_dheap_deletemin (
+ EGLPNUM_TYPENAME_ILLdheap * h,
+ int *i)
+{
+ int j;
+
+ if (h->size == 0)
+ *i = -1;
+ else
+ {
+ j = h->entry[0];
+ EGLPNUM_TYPENAME_ILLutil_dheap_delete (h, j);
+ *i = j;
+ }
+}
+
+void EGLPNUM_TYPENAME_ILLutil_dheap_changekey (
+ EGLPNUM_TYPENAME_ILLdheap * h,
+ int i,
+ EGLPNUM_TYPE * newkey)
+{
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (*newkey, h->key[i]))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (h->key[i], *newkey);
+ dheap_siftup (h, i, h->loc[i]);
+ }
+ else if (EGLPNUM_TYPENAME_EGlpNumIsLess (h->key[i], *newkey))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (h->key[i], *newkey);
+ dheap_siftdown (h, i, h->loc[i]);
+ }
+}
+
+static void dheap_siftup (
+ EGLPNUM_TYPENAME_ILLdheap * h,
+ int i,
+ int x)
+{
+ int p;
+
+ p = HEAP_UP (x);
+ while (x && EGLPNUM_TYPENAME_EGlpNumIsLess (h->key[i], h->key[h->entry[p]]))
+ {
+ h->entry[x] = h->entry[p];
+ h->loc[h->entry[p]] = x;
+ x = p;
+ p = HEAP_UP (p);
+ }
+ h->entry[x] = i;
+ h->loc[i] = x;
+}
+
+static void dheap_siftdown (
+ EGLPNUM_TYPENAME_ILLdheap * h,
+ int i,
+ int x)
+{
+ int c;
+
+ c = dheap_minchild (x, h);
+
+ while (c >= 0 && EGLPNUM_TYPENAME_EGlpNumIsLess (h->key[h->entry[c]], h->key[i]))
+ {
+ h->entry[x] = h->entry[c];
+ h->loc[h->entry[c]] = x;
+ x = c;
+ c = dheap_minchild (c, h);
+ }
+ h->entry[x] = i;
+ h->loc[i] = x;
+}
+
+static int dheap_minchild (
+ int x,
+ EGLPNUM_TYPENAME_ILLdheap * h)
+{
+ int c = HEAP_DOWN (x);
+ int cend;
+ EGLPNUM_TYPE minval;
+ int minloc;
+
+ if (c >= h->size)
+ return -1;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (minval);
+ EGLPNUM_TYPENAME_EGlpNumCopy (minval, h->key[h->entry[c]]);
+ minloc = c;
+ cend = c + HEAP_D;
+ if (h->size < cend)
+ cend = h->size;
+ for (c++; c < cend; c++)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (h->key[h->entry[c]], minval))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (minval, h->key[h->entry[c]]);
+ minloc = c;
+ }
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (minval);
+ return minloc;
+}
diff --git a/qsopt_ex/dheaps_i.h b/qsopt_ex/dheaps_i.h
new file mode 100644
index 0000000..e4ecfcd
--- /dev/null
+++ b/qsopt_ex/dheaps_i.h
@@ -0,0 +1,72 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+#ifndef EGLPNUM_TYPENAME___DHEAPS_I_H__
+#define EGLPNUM_TYPENAME___DHEAPS_I_H__
+
+#include "eg_lpnum.h"
+
+/****************************************************************************/
+/* */
+/* dheaps_i.c */
+/* */
+/****************************************************************************/
+
+typedef struct EGLPNUM_TYPENAME_ILLdheap
+{
+ EGLPNUM_TYPE *key;
+ int *entry;
+ int *loc;
+ int total_space;
+ int size;
+}
+EGLPNUM_TYPENAME_ILLdheap;
+
+void EGLPNUM_TYPENAME_ILLutil_dheap_free (
+ EGLPNUM_TYPENAME_ILLdheap * h),
+ EGLPNUM_TYPENAME_ILLutil_dheap_delete (
+ EGLPNUM_TYPENAME_ILLdheap * h,
+ int i),
+ EGLPNUM_TYPENAME_ILLutil_dheap_changekey (
+ EGLPNUM_TYPENAME_ILLdheap * h,
+ int i,
+ EGLPNUM_TYPE * newkey),
+ EGLPNUM_TYPENAME_ILLutil_dheap_findmin (
+ EGLPNUM_TYPENAME_ILLdheap * h,
+ int *i),
+ EGLPNUM_TYPENAME_ILLutil_dheap_deletemin (
+ EGLPNUM_TYPENAME_ILLdheap * h,
+ int *i);
+
+int EGLPNUM_TYPENAME_ILLutil_dheap_init (
+ EGLPNUM_TYPENAME_ILLdheap * h,
+ int k),
+ EGLPNUM_TYPENAME_ILLutil_dheap_resize (
+ EGLPNUM_TYPENAME_ILLdheap * h,
+ int newsize),
+ EGLPNUM_TYPENAME_ILLutil_dheap_insert (
+ EGLPNUM_TYPENAME_ILLdheap * h,
+ int i);
+
+
+
+#endif
diff --git a/qsopt_ex/dstruct.c b/qsopt_ex/dstruct.c
new file mode 100644
index 0000000..5c25162
--- /dev/null
+++ b/qsopt_ex/dstruct.c
@@ -0,0 +1,499 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: dstruct.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+static int TRACE = 0;
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "logging-private.h"
+
+#include "allocrus.h"
+#include "eg_lpnum.h"
+#include "eg_io.h"
+#include "except.h"
+
+#include "dstruct_EGLPNUM_TYPENAME.h"
+#include "qsopt_EGLPNUM_TYPENAME.h"
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+
+/****************************************************************************/
+/* */
+/* EGLPNUM_TYPENAME_svector */
+/* */
+/* Written by: Applegate, Cook, Dash */
+/* Date: */
+/* */
+/* EXPORTED FUNCTIONS: */
+/* */
+/****************************************************************************/
+
+void EGLPNUM_TYPENAME_ILLsvector_init (
+ EGLPNUM_TYPENAME_svector * s)
+{
+ s->nzcnt = 0;
+ s->indx = 0;
+ s->coef = 0;
+}
+
+void EGLPNUM_TYPENAME_ILLsvector_free (
+ EGLPNUM_TYPENAME_svector * s)
+{
+ ILL_IFFREE (s->indx, int);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (s->coef);
+ s->nzcnt = 0;
+}
+
+int EGLPNUM_TYPENAME_ILLsvector_alloc (
+ EGLPNUM_TYPENAME_svector * s,
+ int nzcnt)
+{
+ int rval = 0;
+
+ s->nzcnt = nzcnt;
+ if (nzcnt == 0)
+ {
+ s->indx = 0;
+ s->coef = 0;
+ }
+ else
+ {
+ ILL_SAFE_MALLOC (s->indx, nzcnt, int);
+
+ s->coef = EGLPNUM_TYPENAME_EGlpNumAllocArray (nzcnt);
+ }
+ return 0;
+CLEANUP:
+ ILL_IFFREE (s->indx, int);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (s->coef);
+ ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLsvector_alloc");
+}
+
+int EGLPNUM_TYPENAME_ILLsvector_copy (
+ const EGLPNUM_TYPENAME_svector * s_in,
+ EGLPNUM_TYPENAME_svector * s_out)
+{
+ int i;
+ int nzcnt = s_in->nzcnt;
+ int rval = 0;
+
+ rval = EGLPNUM_TYPENAME_ILLsvector_alloc (s_out, nzcnt);
+ ILL_CLEANUP_IF (rval);
+ for (i = 0; i < nzcnt; i++)
+ {
+ s_out->indx[i] = s_in->indx[i];
+ EGLPNUM_TYPENAME_EGlpNumCopy (s_out->coef[i], s_in->coef[i]);
+ }
+
+CLEANUP:
+ ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLsvector_copy");
+}
+
+/****************************************************************************/
+/* */
+/* EGLPNUM_TYPENAME_heap */
+/* */
+/* Written by: Applegate, Cook, Dash */
+/* Date: */
+/* */
+/* EXPORTED FUNCTIONS: */
+/* */
+/****************************************************************************/
+
+#define DEBUG_HEAP 0
+
+#define HEAP_D 3
+#define HEAP_UP(x) (((x)-1)/HEAP_D)
+#define HEAP_DOWN(x) (((x)*HEAP_D)+1)
+
+static int siftup (
+ EGLPNUM_TYPENAME_heap * h,
+ int hloc,
+ int ix),
+ siftdown (
+ EGLPNUM_TYPENAME_heap * h,
+ int hloc,
+ int ix),
+ maxchild (
+ EGLPNUM_TYPENAME_heap * h,
+ int hloc);
+
+static int siftup (
+ EGLPNUM_TYPENAME_heap * h,
+ int hloc,
+ int ix)
+{
+ int i = hloc;
+ int p = HEAP_UP (i);
+ EGLPNUM_TYPE val;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (val);
+ EGLPNUM_TYPENAME_EGlpNumCopy (val, h->key[ix]);
+
+ while (i > 0 && EGLPNUM_TYPENAME_EGlpNumIsLess (h->key[h->entry[p]], val))
+ {
+ h->entry[i] = h->entry[p];
+ h->loc[h->entry[i]] = i;
+ i = p;
+ p = HEAP_UP (p);
+ }
+ h->entry[i] = ix;
+ h->loc[ix] = i;
+ ILL_IFTRACE2 ("%s:%la:%d:%d:%d\n", __func__, EGLPNUM_TYPENAME_EGlpNumToLf (val), hloc, ix, i);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (val);
+ return i;
+}
+
+static int siftdown (
+ EGLPNUM_TYPENAME_heap * h,
+ int hloc,
+ int ix)
+{
+ int i = hloc;
+ int c = maxchild (h, i);
+ EGLPNUM_TYPE val;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (val);
+ EGLPNUM_TYPENAME_EGlpNumCopy (val, h->key[ix]);
+ ILL_IFTRACE2 ("%s:%d:%d:%d:%la", __func__, hloc, ix, c, EGLPNUM_TYPENAME_EGlpNumToLf (val));
+
+ while (c != -1 && EGLPNUM_TYPENAME_EGlpNumIsLess (val, h->key[h->entry[c]]))
+ {
+ h->entry[i] = h->entry[c];
+ h->loc[h->entry[i]] = i;
+ i = c;
+ c = maxchild (h, c);
+ }
+ h->entry[i] = ix;
+ h->loc[ix] = i;
+ EGLPNUM_TYPENAME_EGlpNumClearVar (val);
+ ILL_IFTRACE2 ("%s:%d:%d\n", __func__, ix, i);
+ return i;
+}
+
+//extern EGLPNUM_TYPE EGLPNUM_TYPENAME_ILL_MINDOUBLE;
+static int maxchild (
+ EGLPNUM_TYPENAME_heap * h,
+ int hloc)
+{
+ int i;
+ int mc = -1;
+ int hmin = HEAP_D * hloc + 1;
+ int hmax = HEAP_D * hloc + HEAP_D;
+ EGLPNUM_TYPE val;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (val);
+ EGLPNUM_TYPENAME_EGlpNumCopy (val, EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+ ILL_IFTRACE2 (" %s:%d", __func__, hloc);
+
+ for (i = hmin; i <= hmax && i < h->size; i++)
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (val, h->key[h->entry[i]]))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (val, h->key[h->entry[i]]);
+ mc = i;
+ ILL_IFTRACE2 (":%d:%la", mc, EGLPNUM_TYPENAME_EGlpNumToLf (val));
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (val);
+ ILL_IFTRACE2 ("\n");
+ return mc;
+}
+
+#if DEBUG_HEAP > 0
+
+static void printheap (
+ EGLPNUM_TYPENAME_heap * h)
+{
+ int i;
+
+ QSlog("entry (%d): ", h->size);
+ for (i = 0; i < h->size; i++)
+ QSlog("%d ", h->entry[i]);
+ QSlog(" loc: ");
+ for (i = 0; i < h->maxsize; i++)
+ QSlog("%d ", h->loc[i]);
+ QSlog("\n key: ");
+ for (i = 0; i < h->maxsize; i++)
+ QSlog("%la ", EGLPNUM_TYPENAME_EGlpNumToLf (h->key[i]));
+ QSlog("\n key(sorted): ");
+ for (i = 0; i < h->size; i++)
+ QSlog("%la ", EGLPNUM_TYPENAME_EGlpNumToLf (h->key[h->entry[i]]));
+}
+
+static void heapcheck (
+ EGLPNUM_TYPENAME_heap * h)
+{
+ int i, tcnt = 0;
+
+ for (i = 0; i < h->maxsize; i++)
+ {
+ if (h->loc[i] < -1)
+ QSlog("error in EGLPNUM_TYPENAME_heap\n");
+ else if (h->loc[i] > -1)
+ tcnt++;
+ }
+ if (tcnt != h->size)
+ QSlog("error 3 in EGLPNUM_TYPENAME_heap\n");
+
+ for (i = 0; i < h->size; i++)
+ {
+ if (h->loc[h->entry[i]] != i)
+ QSlog("error 1 in EGLPNUM_TYPENAME_heap\n");
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (h->key[h->entry[i]]))
+ QSlog("error 2 in EGLPNUM_TYPENAME_heap\n");
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (h->key[h->entry[HEAP_UP (i)]], h->key[h->entry[i]]))
+ QSlog("error 4 in EGLPNUM_TYPENAME_heap\n");
+ }
+}
+
+#endif
+
+void EGLPNUM_TYPENAME_ILLheap_insert (
+ EGLPNUM_TYPENAME_heap * const h,
+ int const ix)
+{
+ int i = h->size;
+
+ ILL_IFTRACE ("%s:%d:%la\n", __func__, ix, EGLPNUM_TYPENAME_EGlpNumToLf (h->key[ix]));
+
+ i = siftup (h, i, ix);
+ h->size++;
+
+#if DEBUG_HEAP > 0
+ heapcheck (h);
+#endif
+#if DEBUG_HEAP > 1
+ printheap (h);
+#endif
+}
+
+void EGLPNUM_TYPENAME_ILLheap_modify (
+ EGLPNUM_TYPENAME_heap * const h,
+ int const ix)
+{
+ int i = h->loc[ix];
+ int pi = i;
+
+ ILL_IFTRACE ("%s:%d\n", __func__, ix);
+
+ if (h->loc[ix] == -1)
+ return;
+ i = siftup (h, i, ix);
+ if (pi == i)
+ i = siftdown (h, i, ix);
+
+#if DEBUG_HEAP > 0
+ heapcheck (h);
+#endif
+#if DEBUG_HEAP > 1
+ printheap (h);
+#endif
+}
+
+void EGLPNUM_TYPENAME_ILLheap_delete (
+ EGLPNUM_TYPENAME_heap * const h,
+ int const ix)
+{
+ int i = h->loc[ix];
+ int pi = i;
+ int nix = h->entry[h->size - 1];
+
+ ILL_IFTRACE ("%s:%d:%d:%d\n", __func__, ix, nix, pi);
+
+ h->loc[ix] = -1;
+ h->size--;
+ if (nix == ix)
+ {
+#if DEBUG_HEAP > 0
+ heapcheck (h);
+#endif
+#if DEBUG_HEAP > 1
+ printheap (h);
+#endif
+ return;
+ }
+
+ h->entry[i] = nix;
+ h->loc[nix] = i;
+
+ i = siftup (h, i, nix);
+ ILL_IFTRACE ("%s:%d:%d:%d:%d\n", __func__, ix, nix, pi, i);
+ if (pi == i)
+ siftdown (h, i, nix);
+
+#if DEBUG_HEAP > 0
+ heapcheck (h);
+#endif
+#if DEBUG_HEAP > 1
+ printheap (h);
+#endif
+}
+
+int EGLPNUM_TYPENAME_ILLheap_findmin (
+ EGLPNUM_TYPENAME_heap * const h)
+{
+ if (h->hexist == 0 || h->size <= 0)
+ return -1;
+ return h->entry[0];
+}
+
+void EGLPNUM_TYPENAME_ILLheap_init (
+ EGLPNUM_TYPENAME_heap * const h)
+{
+ h->entry = NULL;
+ h->loc = NULL;
+ h->key = NULL;
+ h->hexist = 0;
+}
+
+int EGLPNUM_TYPENAME_ILLheap_build (
+ EGLPNUM_TYPENAME_heap * const h,
+ int const nelems,
+ EGLPNUM_TYPE * key)
+{
+ int rval = 0;
+ int i, n = 0;
+
+ ILL_IFTRACE ("%s:%d\n", __func__, nelems);
+
+ h->hexist = 1;
+ h->size = 0;
+ h->maxsize = nelems;
+ h->key = key;
+ ILL_SAFE_MALLOC (h->entry, nelems, int);
+ ILL_SAFE_MALLOC (h->loc, nelems, int);
+
+ for (i = 0; i < nelems; i++)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (key[i]))
+ {
+ h->entry[n] = i;
+ h->loc[i] = n;
+ n++;
+ }
+ else
+ h->loc[i] = -1;
+ }
+ h->size = n;
+ for (i = n - 1; i >= 0; i--)
+ {
+ ILL_IFTRACE2 ("insert %la\n", EGLPNUM_TYPENAME_EGlpNumToLf (h->key[h->entry[i]]));
+ siftdown (h, i, h->entry[i]);
+ }
+
+#if DEBUG_HEAP > 0
+ heapcheck (h);
+#endif
+#if DEBUG_HEAP > 1
+ printheap (h);
+#endif
+
+CLEANUP:
+ if (rval)
+ EGLPNUM_TYPENAME_ILLheap_free (h);
+ ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLheap_init");
+}
+
+void EGLPNUM_TYPENAME_ILLheap_free (
+ EGLPNUM_TYPENAME_heap * const h)
+{
+ if (h->hexist)
+ {
+ ILL_IFFREE (h->entry, int);
+ ILL_IFFREE (h->loc, int);
+
+ h->hexist = 0;
+ h->maxsize = 0;
+ h->size = 0;
+ }
+}
+
+
+/****************************************************************************/
+/* */
+/* matrix */
+/* */
+/* Written by: Applegate, Cook, Dash */
+/* Date: */
+/* */
+/* EXPORTED FUNCTIONS: */
+/* */
+/****************************************************************************/
+
+void EGLPNUM_TYPENAME_ILLmatrix_init (
+ EGLPNUM_TYPENAME_ILLmatrix * A)
+{
+ if (A)
+ {
+ A->matval = 0;
+ A->matcnt = 0;
+ A->matbeg = 0;
+ A->matind = 0;
+ A->matcols = 0;
+ A->matcolsize = 0;
+ A->matrows = 0;
+ A->matsize = 0;
+ A->matfree = 0;
+ }
+}
+
+void EGLPNUM_TYPENAME_ILLmatrix_free (
+ EGLPNUM_TYPENAME_ILLmatrix * A)
+{
+ if (A)
+ {
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (A->matval);
+ ILL_IFFREE (A->matcnt, int);
+ ILL_IFFREE (A->matbeg, int);
+ ILL_IFFREE (A->matind, int);
+
+ EGLPNUM_TYPENAME_ILLmatrix_init (A);
+ }
+}
+
+void EGLPNUM_TYPENAME_ILLmatrix_prt (
+ EGioFile_t * fd,
+ EGLPNUM_TYPENAME_ILLmatrix * A)
+{
+ int j, k;
+
+ if (A == NULL)
+ {
+ EGioPrintf (fd, "Matrix %p: empty\n", (void *) A);
+ }
+ else
+ {
+ EGioPrintf (fd, "Matrix %p: nrows = %d ncols = %d\n",
+ (void *) A, A->matrows, A->matcols);
+ for (j = 0; j < A->matcols; j++)
+ {
+ EGioPrintf (fd, "col %d: ", j);
+ for (k = A->matbeg[j]; k < A->matbeg[j] + A->matcnt[j]; k++)
+ {
+ EGioPrintf (fd, "row %d=%.3f ", A->matind[k], EGLPNUM_TYPENAME_EGlpNumToLf (A->matval[k]));
+ }
+ EGioPrintf (fd, "\n");
+ }
+ }
+}
diff --git a/qsopt_ex/dstruct.h b/qsopt_ex/dstruct.h
new file mode 100644
index 0000000..d741bb7
--- /dev/null
+++ b/qsopt_ex/dstruct.h
@@ -0,0 +1,134 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCSINFO $Id: dstruct_EGLPNUM_TYPENAME.h,v 1.3 2003/11/05 16:57:39 meven Exp $ */
+/****************************************************************************/
+/* */
+/* EGLPNUM_TYPENAME_svector.h */
+/* */
+/****************************************************************************/
+
+#ifndef EGLPNUM_TYPENAME___SVECTOR_H
+#define EGLPNUM_TYPENAME___SVECTOR_H
+
+#include "eg_io.h"
+
+typedef struct EGLPNUM_TYPENAME_svector
+{
+ int nzcnt;
+ int *indx;
+ int size;
+ EGLPNUM_TYPE *coef;
+}
+EGLPNUM_TYPENAME_svector;
+
+void EGLPNUM_TYPENAME_ILLsvector_init (
+ EGLPNUM_TYPENAME_svector * s),
+ EGLPNUM_TYPENAME_ILLsvector_free (
+ EGLPNUM_TYPENAME_svector * s);
+
+int EGLPNUM_TYPENAME_ILLsvector_alloc (
+ EGLPNUM_TYPENAME_svector * s,
+ int nzcnt),
+ EGLPNUM_TYPENAME_ILLsvector_copy (
+ const EGLPNUM_TYPENAME_svector * s_in,
+ EGLPNUM_TYPENAME_svector * s_out);
+
+#endif /* EGLPNUM_TYPENAME___SVECTOR_H */
+
+/****************************************************************************/
+/* */
+/* EGLPNUM_TYPENAME_heap.h */
+/* */
+/****************************************************************************/
+
+#ifndef EGLPNUM_TYPENAME___HEAP_H
+#define EGLPNUM_TYPENAME___HEAP_H
+
+typedef struct
+{
+ int *entry;
+ int *loc;
+ EGLPNUM_TYPE *key;
+ int hexist;
+ int maxsize;
+ int size;
+}
+EGLPNUM_TYPENAME_heap;
+
+void EGLPNUM_TYPENAME_ILLheap_insert (
+ EGLPNUM_TYPENAME_heap * const h,
+ int const ix),
+ EGLPNUM_TYPENAME_ILLheap_modify (
+ EGLPNUM_TYPENAME_heap * const h,
+ int const ix),
+ EGLPNUM_TYPENAME_ILLheap_delete (
+ EGLPNUM_TYPENAME_heap * const h,
+ int const ix),
+ EGLPNUM_TYPENAME_ILLheap_init (
+ EGLPNUM_TYPENAME_heap * const h),
+ EGLPNUM_TYPENAME_ILLheap_free (
+ EGLPNUM_TYPENAME_heap * const h);
+
+int EGLPNUM_TYPENAME_ILLheap_findmin (
+ EGLPNUM_TYPENAME_heap * const h),
+ EGLPNUM_TYPENAME_ILLheap_build (
+ EGLPNUM_TYPENAME_heap * const h,
+ int const nelems,
+ EGLPNUM_TYPE * key);
+
+#endif /* EGLPNUM_TYPENAME___HEAP_H */
+
+/****************************************************************************/
+/* */
+/* matrix.h */
+/* */
+/****************************************************************************/
+
+#ifndef EGLPNUM_TYPENAME___MATRIX_H
+#define EGLPNUM_TYPENAME___MATRIX_H
+
+typedef struct EGLPNUM_TYPENAME_ILLmatrix
+{
+ EGLPNUM_TYPE *matval; /* The coefficients. */
+ int *matcnt; /* Number of coefs in each col. */
+ int *matind; /* The row indices of the coefs. */
+ int *matbeg; /* The start of each col. */
+ int matcols; /* Number of columns. */
+ int matrows;
+ int matcolsize; /* Length of matbeg and matcnt. */
+ int matsize; /* Length of matind and matval. */
+ int matfree; /* Free space at end of matind. */
+ /* Note: free elements marked by -1 in */
+ /* matind; we keep at least 1 free at end. */
+}
+EGLPNUM_TYPENAME_ILLmatrix;
+
+void EGLPNUM_TYPENAME_ILLmatrix_init (
+ EGLPNUM_TYPENAME_ILLmatrix * A);
+void EGLPNUM_TYPENAME_ILLmatrix_free (
+ EGLPNUM_TYPENAME_ILLmatrix * A);
+void EGLPNUM_TYPENAME_ILLmatrix_prt (
+ EGioFile_t * fd,
+ EGLPNUM_TYPENAME_ILLmatrix * A);
+
+#endif /* EGLPNUM_TYPENAME___MATRIX_H */
diff --git a/qsopt_ex/editor.c b/qsopt_ex/editor.c
new file mode 100644
index 0000000..47d7b48
--- /dev/null
+++ b/qsopt_ex/editor.c
@@ -0,0 +1,789 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: editor.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "eg_lpnum.h"
+#include "eg_io.h"
+#include "except.h"
+#include "util.h"
+
+#include "qsopt_EGLPNUM_TYPENAME.h"
+#include "lpdata_EGLPNUM_TYPENAME.h"
+#include "qstruct_EGLPNUM_TYPENAME.h"
+#include "qsopt_EGLPNUM_TYPENAME.h"
+#include "editor_EGLPNUM_TYPENAME.h"
+#include "readline_EGLPNUM_TYPENAME.h"
+#include "rawlp_EGLPNUM_TYPENAME.h"
+#include "stddefs.h" /* for MAX */
+#include "read_lp_EGLPNUM_TYPENAME.h"
+#include "lp_EGLPNUM_TYPENAME.h"
+#include "lib_EGLPNUM_TYPENAME.h"
+
+static int TRACE = 0;
+
+#define ILL_BREAK_BODY_IF(rval) if (rval != 0) goto CLEANUP
+#define ILL_BREAK_BODY goto CLEANUP
+
+static int transpose ( EGLPNUM_TYPENAME_rawlpdata * lp);
+static int pull_info_from_p ( EGLPNUM_TYPENAME_QSdata * p, EGLPNUM_TYPENAME_rawlpdata * lp);
+static void add_row ( EGLPNUM_TYPENAME_QSdata * p, EGLPNUM_TYPENAME_rawlpdata * lp, EGLPNUM_TYPENAME_ILLread_lp_state * state);
+
+/* static int new_row(EGLPNUM_TYPENAME_QSdata *p, EGLPNUM_TYPENAME_rawlpdata *lp, EGLPNUM_TYPENAME_ILLread_lp_state *state); */
+static void del_row ( EGLPNUM_TYPENAME_QSdata * p, EGLPNUM_TYPENAME_rawlpdata * lp, EGLPNUM_TYPENAME_ILLread_lp_state * state);
+
+static void add_col ( EGLPNUM_TYPENAME_QSdata * p, EGLPNUM_TYPENAME_rawlpdata * lp, EGLPNUM_TYPENAME_ILLread_lp_state * state);
+static void del_col ( EGLPNUM_TYPENAME_QSdata * p, EGLPNUM_TYPENAME_rawlpdata * lp, EGLPNUM_TYPENAME_ILLread_lp_state * state);
+
+#define NONE -1
+#define QS_EXIT 0
+#define ROW 1
+#define COL 2
+#define PLP 3
+#define PRTX 4
+#define SOLVE 5
+#define PMPS 6
+#define HELP 7
+#define DEL 8
+#define NEW 9
+#define ADD 10
+#define PRIMAL 11
+#define DUAL 12
+#define NCOMMAND 13
+static const char *commands[NCOMMAND + 1];
+static char hasSubCmd[NCOMMAND + 1];
+
+void EGLPNUM_TYPENAME_ILLeditor_init (
+ void)
+{
+ commands[QS_EXIT] = "QS_EXIT";
+ commands[ROW] = "ROW";
+ commands[COL] = "COL";
+ commands[PLP] = "LP";
+ commands[PMPS] = "MPS";
+ commands[SOLVE] = "SOLVE";
+ commands[PRTX] = "PRT";
+ commands[HELP] = "HELP";
+ commands[ADD] = "ADD";
+ commands[DEL] = "DEL";
+ commands[NEW] = "NEW";
+ commands[PRIMAL] = "PRIMAL";
+ commands[DUAL] = "DUAL";
+ commands[NCOMMAND] = NULL;
+
+ hasSubCmd[QS_EXIT] = 0;
+ hasSubCmd[ROW] = 1;
+ hasSubCmd[COL] = 1;
+ hasSubCmd[PLP] = 0;
+ hasSubCmd[PMPS] = 0;
+ hasSubCmd[SOLVE] = 1;
+ hasSubCmd[PRTX] = 0;
+ hasSubCmd[HELP] = 0;
+ hasSubCmd[ADD] = 1;
+ hasSubCmd[DEL] = 1;
+ hasSubCmd[NEW] = 1;
+ hasSubCmd[PRIMAL] = 1;
+ hasSubCmd[DUAL] = 1;
+ hasSubCmd[NCOMMAND] = 0;
+}
+
+static void ILLeditor_help_cmd (
+ int cmd,
+ int subcmd);
+
+static void ILLeditor_help (
+ void)
+{
+ ILLeditor_help_cmd (ROW, ADD);
+ /* ILLeditor_help_cmd(ROW, NEW); */
+ ILLeditor_help_cmd (ROW, DEL);
+ ILLeditor_help_cmd (COL, ADD);
+ ILLeditor_help_cmd (COL, DEL);
+ ILLeditor_help_cmd (SOLVE, NONE);
+ ILLeditor_help_cmd (PRTX, NONE);
+ ILLeditor_help_cmd (PLP, NONE);
+ ILLeditor_help_cmd (PMPS, NONE);
+ ILLeditor_help_cmd (QS_EXIT, NONE);
+ ILLeditor_help_cmd (HELP, NONE);
+}
+
+static void ILLeditor_help_cmd (
+ int cmd,
+ int subcmd)
+{
+ if (cmd == ROW && subcmd == ADD)
+ QSlog("%s ADD:\t%s.",
+ commands[ROW], "add a row; enter in LP format");
+ if (cmd == COL && subcmd == ADD)
+ QSlog("%s ADD:\t%s.",
+ commands[COL], "add a col; enter in LP format");
+ /* if (cmd == ROW && subcmd == NEW)
+ * QSlog("%s NEW:\t%s.",
+ * commands[ROW], "new row; enter rowname: sense rhs");
+ */
+ if (cmd == ROW && subcmd == DEL)
+ QSlog("%s DEL:\t%s.",
+ commands[ROW], "delete a row; give rowname");
+ if (cmd == COL && subcmd == DEL)
+ QSlog("%s DEL:\t%s.",
+ commands[COL], "delete a col; give colname");
+ if (cmd == SOLVE)
+ QSlog("%s:\t%s.", commands[SOLVE], "solve problem");
+ if (cmd == PRTX)
+ QSlog("%s:\t%s.",
+ commands[PRTX], "print variable values for optimal solution");
+ if (cmd == PLP)
+ QSlog("%s [file]:\t%s.",
+ commands[PLP], "print problem in LP format to file or stdout");
+ if (cmd == PMPS)
+ QSlog("%s [file]:\t%s.",
+ commands[PMPS], "print problem in MPS format to file or stdout");
+ if (cmd == QS_EXIT)
+ QSlog("%s:\t%s.", commands[QS_EXIT], "QS_EXIT");
+ if (cmd == HELP)
+ QSlog("%s:\t%s.", commands[HELP], "print this help");
+}
+
+static void getCmd (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ int *cmd,
+ int *subcmd)
+{
+ const char *cmd_str, *subcmd_str;
+ int tmp;
+
+ *cmd = ILLutil_index (commands, state->field);
+ *subcmd = -1;
+ if (hasSubCmd[*cmd] && (EGLPNUM_TYPENAME_ILLread_lp_state_next_field_on_line (state) == 0))
+ {
+ *subcmd = ILLutil_index (commands, state->field);
+ if ((*subcmd == ROW) || (*subcmd == COL) || (*subcmd == SOLVE))
+ {
+ ILL_SWAP (*subcmd, *cmd, tmp);
+ }
+ }
+ cmd_str = (*cmd >= 0) ? commands[*cmd] : "???";
+ subcmd_str = (*subcmd >= 0) ? commands[*subcmd] : "???";
+ ILL_IFTRACE ("cmd = %s, subcmd = %s\n", cmd_str, subcmd_str);
+}
+
+void EGLPNUM_TYPENAME_ILLeditor (
+ EGLPNUM_TYPENAME_QSdata * p)
+{
+ EGLPNUM_TYPENAME_rawlpdata raw, *lp = &raw;
+ int cmd, subcmd, tval, rval = 0;
+ EGLPNUM_TYPENAME_ILLread_lp_state lpstate, *state = &lpstate;
+ EGLPNUM_TYPENAME_qsline_reader *reader;
+
+ ILL_IFTRACE ("EGLPNUM_TYPENAME_ILLeditor\n");
+
+ reader = EGLPNUM_TYPENAME_ILLline_reader_new ((EGLPNUM_TYPENAME_qsread_line_fct) fgets, stdin);
+ rval = EGLPNUM_TYPENAME_ILLread_lp_state_init (state, reader, "STDIN", 1);
+ rval = rval || pull_info_from_p (p, lp);
+ ILL_BREAK_BODY_IF (rval);
+
+ while (EGLPNUM_TYPENAME_ILLread_lp_state_next_field (state) == 0)
+ {
+ getCmd (state, &cmd, &subcmd);
+ switch (cmd)
+ {
+ case QS_EXIT:
+ ILL_BREAK_BODY;
+
+ case ROW:
+ {
+ switch (subcmd)
+ {
+ case ADD:
+ add_row (p, lp, state);
+ break;
+ /* case NEW: rval = new_row(p, lp, state); break; */
+ case DEL:
+ del_row (p, lp, state);
+ break;
+ default:
+ ILLeditor_help ();
+ break;
+ }
+ break;
+ }
+ case COL:
+ {
+ switch (subcmd)
+ {
+ case ADD:
+ add_col (p, lp, state);
+ break;
+ case DEL:
+ del_col (p, lp, state);
+ break;
+ default:
+ ILLeditor_help ();
+ break;
+ }
+ break;
+ }
+
+ case SOLVE:
+ {
+ if (subcmd == PRIMAL)
+ {
+ (void) EGLPNUM_TYPENAME_ILLeditor_solve (p, PRIMAL_SIMPLEX);
+ }
+ else if (subcmd == DUAL)
+ {
+ (void) EGLPNUM_TYPENAME_ILLeditor_solve (p, DUAL_SIMPLEX);
+ }
+ else
+ {
+ ILLeditor_help ();
+ }
+ break;
+ }
+
+ case PRTX:
+ {
+ EGioFile_t*lout = EGioOpenFILE(stdout);
+ if ((rval = EGLPNUM_TYPENAME_ILLlib_print_x (lout, p->lp, 0, 0, 1)))
+ {
+ QSlog("The problem may not be feasible.");
+ }
+ EGioClose(lout);
+ break;
+ }
+
+ case PLP:
+ case PMPS:
+ {
+ if (EGLPNUM_TYPENAME_ILLread_lp_state_next_field_on_line (state) == 0)
+ {
+ if (cmd == PMPS)
+ {
+ tval = EGLPNUM_TYPENAME_QSwrite_prob (p, state->field, "MPS");
+ }
+ else
+ {
+ tval = EGLPNUM_TYPENAME_QSwrite_prob (p, state->field, "LP");
+ }
+ if (tval)
+ {
+ QSlog("Could not write problem to \"%s\".",
+ state->field);
+ }
+ else
+ {
+ QSlog("Saved to \"%s\".", state->field);
+ }
+ }
+ else
+ {
+ if (cmd == PMPS)
+ {
+ (void) EGLPNUM_TYPENAME_QSwrite_prob_file (p, stdout, "MPS");
+ }
+ else
+ {
+ (void) EGLPNUM_TYPENAME_QSwrite_prob_file (p, stdout, "LP");
+ }
+ }
+ break;
+ }
+
+ case NONE:
+ QSlog("Unknown command: %s", state->field);
+ default:
+ ILLeditor_help ();
+ break;
+ }
+ EGLPNUM_TYPENAME_ILLread_lp_state_next_line (state);
+ }
+CLEANUP:
+ EGLPNUM_TYPENAME_ILLline_reader_free (reader);
+ EGLPNUM_TYPENAME_ILLfree_rawlpdata (lp);
+}
+
+int EGLPNUM_TYPENAME_ILLeditor_solve (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int salgo)
+{
+ int rval = 0;
+ int status = 0;
+ EGLPNUM_TYPE val;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (val);
+
+ if (salgo == PRIMAL_SIMPLEX)
+ {
+ rval = EGLPNUM_TYPENAME_QSopt_primal (p, &status);
+ }
+ else
+ {
+ rval = EGLPNUM_TYPENAME_QSopt_dual (p, &status);
+ }
+ ILL_BREAK_BODY_IF (rval);
+ rval = EGLPNUM_TYPENAME_QSget_objval (p, &val);
+ if (p->simplex_display)
+ if (rval == 0)
+ {
+ QSlog("LP Value: %.6f, status %d", EGLPNUM_TYPENAME_EGlpNumToLf (val),
+ status);
+ }
+CLEANUP:
+ EGLPNUM_TYPENAME_EGlpNumClearVar (val);
+ ILL_RESULT (rval, "EGLPNUM_TYPENAME_ILLeditor_solve");
+}
+
+
+static int pull_info_from_p (
+ EGLPNUM_TYPENAME_QSdata * p,
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+ int i, rval = 0;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp = p->lp->O;
+ int nrows, ncols;
+
+ EGLPNUM_TYPENAME_ILLinit_rawlpdata (lp, NULL);
+ rval = ILLsymboltab_create (&lp->rowtab, 100) ||
+ ILLsymboltab_create (&lp->coltab, 100);
+ ILL_BREAK_BODY_IF (rval);
+
+ nrows = qslp->nrows;
+ ncols = qslp->nstruct;
+ /* add rows to lp */
+ EGLPNUM_TYPENAME_ILLraw_add_row (lp, qslp->objname, 'N', EGLPNUM_TYPENAME_zeroLpNum);
+ for (i = 0; i < nrows; i++)
+ {
+ ILL_FAILfalse (qslp->rownames[i] != NULL, "should have no NULL names");
+ EGLPNUM_TYPENAME_ILLraw_add_row (lp, qslp->rownames[i], qslp->sense[i], qslp->rhs[i]);
+ }
+
+ /* add cols to coltab and lp */
+ for (i = 0; i < ncols; i++)
+ {
+ ILL_FAILfalse (qslp->colnames[i] != NULL, "should have no NULL names");
+ EGLPNUM_TYPENAME_ILLraw_add_col (lp, qslp->colnames[i],
+ (qslp->intmarker) ? qslp->intmarker[i] : 0);
+ }
+CLEANUP:
+ ILL_RETURN (rval, "pull_info_from_p");
+}
+
+static int transpose (
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+ int rval = 0;
+ int tmp;
+ ILLsymboltab tmptab;
+
+ tmp = QSMAX (lp->nrows, lp->ncols);
+ if (tmp >= lp->sensesize)
+ {
+ lp->sensesize *= 1.3;
+ lp->sensesize += 1000;
+ if (lp->sensesize < tmp + 1)
+ lp->sensesize = tmp + 1;
+ lp->rowsense = EGrealloc (lp->rowsense, sizeof (char) * lp->sensesize);
+ //rval = ILLutil_reallocrus_scale ((void **) &lp->rowsense,
+ // &lp->sensesize, tmp + 1,
+ // 1.3, sizeof (char));
+ //ILL_CLEANUP_IF (rval);
+ }
+ if (tmp >= lp->rhssize)
+ {
+ lp->rhssize *= 1.3;
+ lp->rhssize += 1000;
+ if (lp->rhssize < tmp + 1)
+ lp->rhssize = tmp + 1;
+ EGLPNUM_TYPENAME_EGlpNumReallocArray (&(lp->rhs), lp->rhssize);
+ //lp->rhs = EGrealloc(lp->rhs, sizeof(double)*lp->rhssize);
+ //rval = ILLutil_reallocrus_scale ((void **) &lp->rhs,
+ // &lp->sensesize, tmp + 1,
+ // 1.3, sizeof (double));
+ //ILL_CLEANUP_IF (rval);
+ }
+ ILL_SWAP (lp->nrows, lp->ncols, tmp);
+ ILL_SWAP (lp->rowtab, lp->coltab, tmptab);
+ ILL_RETURN (rval, "transpose");
+}
+
+static char *get_row_col_name (
+ EGLPNUM_TYPENAME_QSdata * p,
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ int doRow)
+{
+ int rval = 0;
+ int ind;
+ char *rname, *thename = NULL;
+ char buf[ILL_namebufsize];
+ ILLsymboltab *tab = (doRow) ? &lp->rowtab : &lp->coltab;
+ int id = (doRow) ? lp->nrows : lp->ncols;
+
+ id--; /* in EGLPNUM_TYPENAME_rawlpdata obj counts as a row */
+
+ rval = EGLPNUM_TYPENAME_ILLread_constraint_name (state, &rname);
+ ILL_BREAK_BODY_IF (rval);
+
+ if (rname == NULL)
+ {
+ EGLPNUM_TYPENAME_ILLlib_findName (p->qslp, doRow /* forRow */ , rname, id, buf);
+ ILL_UTIL_STR (thename, buf);
+ }
+ else
+ {
+ ILL_UTIL_STR (thename, rname);
+ }
+ if (ILLsymboltab_lookup (tab, thename, &ind) == 0)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlp_error (state, "\"%s\" already exists.", thename);
+ }
+CLEANUP:
+ if (rval != 0)
+ {
+ ILL_IFFREE (thename, char);
+ }
+ return thename;
+}
+
+static int fill_matrix (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ EGLPNUM_TYPENAME_ILLmatrix * m,
+ EGLPNUM_TYPE * obj,
+ int n)
+{
+ int i, cnt, rval = 0;
+ EGLPNUM_TYPENAME_colptr *cp;
+ EGLPNUM_TYPE val;
+ int newCol = (obj != NULL);
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (val);
+
+ /* rely on fact that objective has rowindex 0 */
+
+ m->matrows = lp->nrows;
+ m->matcols = 1;
+ m->matval = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->ncols);
+ ILL_SAFE_MALLOC (m->matind, lp->ncols, int);
+ ILL_SAFE_MALLOC (m->matbeg, 1, int);
+ ILL_SAFE_MALLOC (m->matcnt, 1, int);
+
+ m->matsize = lp->ncols;
+ m->matbeg[0] = 0;
+ m->matcnt[0] = 0;
+ for (i = 0; i < lp->ncols; i++)
+ {
+ cnt = 0;
+ EGLPNUM_TYPENAME_EGlpNumZero (val);
+ for (cp = lp->cols[i]; cp != NULL; cp = cp->next)
+ {
+ ILL_FAILfalse (cp->this_val == n, "n should be the only row around");
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (cp->coef))
+ {
+ EGLPNUM_TYPENAME_EGlpNumAddTo (val, cp->coef);
+ cnt++;
+ }
+ }
+ if (cnt > 1)
+ {
+ EGLPNUM_TYPENAME_ILLlp_warn (state, "Multiple coefficients for \"%s\".",
+ EGLPNUM_TYPENAME_ILLraw_colname (lp, i));
+ }
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (val))
+ {
+ if ((i - newCol) >= 0)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (m->matval[m->matcnt[0]], val);
+ m->matind[m->matcnt[0]] = i - newCol;
+ m->matcnt[0]++;
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (obj[0], val);
+ }
+ }
+ }
+ if (m->matcnt[0] == 0)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlp_error (state, "There are no non zero coefficients.");
+ }
+CLEANUP:
+ EGLPNUM_TYPENAME_EGlpNumClearVar (val);
+ ILL_RESULT (rval, "fill_matrix");
+}
+
+static void add_row (
+ EGLPNUM_TYPENAME_QSdata * p,
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+ int rval = 0;
+ int n;
+ char *name;
+ EGLPNUM_TYPENAME_ILLmatrix m;
+ char sense[1];
+
+ EGLPNUM_TYPENAME_ILLmatrix_init (&m);
+ n = lp->nrows;
+ name = get_row_col_name (p, lp, state, 1 /*doRow */ );
+
+ if (name == NULL)
+ {
+ rval = 1;
+ }
+ else
+ {
+ rval = EGLPNUM_TYPENAME_ILLread_one_constraint (state, name, lp, 0);
+
+ /* adds row name to lp->rowtab the checks constraint expression */
+ if (rval != 0)
+ {
+ /* failed because of error in expression =>
+ * must remove name from symbol table */
+ QSlog("Incorrect expression.");
+ }
+ else
+ {
+ ILL_FAILfalse (lp->nrows == (n + 1), "Should have one row");
+ ILL_IFTRACE ("ADDING row %s.\n", name);
+
+ sense[0] = lp->rowsense[n];
+
+ rval = fill_matrix (lp, state, &m, NULL, n);
+ ILL_BREAK_BODY_IF (rval);
+
+ EGLPNUM_TYPENAME_QSadd_rows (p, 1, m.matcnt, m.matbeg, m.matind, m.matval,
+ &(lp->rhs[n]), sense, (const char **) &name);
+ }
+ }
+CLEANUP:
+ EGLPNUM_TYPENAME_ILLmatrix_free (&m);
+ if (name != NULL)
+ {
+ if (rval != 0)
+ ILLsymboltab_delete (&lp->rowtab, name);
+ ILL_IFFREE (name, char);
+ }
+ if (rval != 0)
+ {
+ lp->nrows = n;
+ }
+ EGLPNUM_TYPENAME_ILLraw_clear_matrix (lp);
+}
+
+static void add_col (
+ EGLPNUM_TYPENAME_QSdata * p,
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+ int rval = 0;
+ int n;
+ char *name[1];
+ int transposed = 1;
+ EGLPNUM_TYPENAME_ILLmatrix matrix, *m = &matrix;
+ EGLPNUM_TYPE obj[1], lower[1], upper[2];
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (*obj);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (*lower);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (upper[0]);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (upper[1]);
+
+ n = lp->ncols;
+ EGLPNUM_TYPENAME_ILLmatrix_init (m);
+ name[0] = get_row_col_name (p, lp, state, 0 /*doRow */ );
+ rval = (name[0] == NULL);
+ ILL_BREAK_BODY_IF (rval);
+
+ transposed = !transpose (lp);
+ rval = EGLPNUM_TYPENAME_ILLread_one_constraint (state, name[0], lp, 0);
+
+ /* adds row name to lp->rowtab the checks constraint expression */
+ if (rval != 0)
+ {
+ /* failed because of error in expression =>
+ * must remove name from symbol table */
+ QSlog("Incorrect expression.");
+ }
+ else
+ {
+ ILL_FAILfalse (lp->nrows == (n + 1), "Should have one row");
+
+ rval = fill_matrix (lp, state, m, obj, n);
+ ILL_BREAK_BODY_IF (rval);
+
+ QSlog("lower ");
+ rval = EGLPNUM_TYPENAME_ILLread_lp_state_next_line (state) ||
+ EGLPNUM_TYPENAME_ILLread_lp_state_value (state, &(lower[0]));
+ ILL_BREAK_BODY_IF (rval);
+
+ QSlog("upper ");
+ rval = EGLPNUM_TYPENAME_ILLread_lp_state_next_line (state) ||
+ EGLPNUM_TYPENAME_ILLread_lp_state_value (state, &(upper[0]));
+ ILL_BREAK_BODY_IF (rval);
+
+ ILL_IFTRACE ("ADDING col %s.\n", name[0]);
+
+ EGLPNUM_TYPENAME_QSadd_cols (p, 1, m->matcnt, m->matbeg, m->matind, m->matval,
+ obj, lower, upper, (const char **) name);
+
+ }
+CLEANUP:
+ EGLPNUM_TYPENAME_ILLmatrix_free (m);
+ if (name[0] != NULL)
+ {
+ if (rval != 0)
+ ILLsymboltab_delete (&lp->rowtab, name[0]);
+ ILL_IFFREE (name[0], char);
+ }
+ if (rval != 0)
+ {
+ lp->nrows = n;
+ }
+ EGLPNUM_TYPENAME_ILLraw_clear_matrix (lp);
+ if (transposed)
+ transpose (lp);
+ ILL_IFFREE (name[0], char);
+
+ EGLPNUM_TYPENAME_EGlpNumClearVar (*obj);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (*lower);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (upper[0]);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (upper[1]);
+}
+
+#if 0
+#ifndef JAVA_PORT
+static void new_row (
+ EGLPNUM_TYPENAME_QSdata * p,
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+ int rval = 0;
+ char *rowname = NULL, *rname = NULL;
+ char sense;
+ double d;
+ int ind, hit;
+
+ rval = EGLPNUM_TYPENAME_ILLread_constraint_name (state, &rname);
+ if (rname == NULL)
+ {
+ rval = 1;
+ ILLeditor_help_cmd (ROW, NEW);
+ }
+ ILL_BREAK_BODY_IF (rval);
+
+ ILLsymboltab_lookup (&lp->rowtab, rname, &ind);
+ if (ind != ILL_SYM_NOINDEX)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlp_error (state, "\"%s\" is already defined.\n", rname);
+ ILL_BREAK_BODY_IF (rval);
+ }
+ ILL_UTIL_STR (rowname, rname);
+
+ rval = EGLPNUM_TYPENAME_ILLread_lp_state_sense (state);
+ sense = state->sense_val;
+ ILL_BREAK_BODY_IF (rval);
+
+ rval = EGLPNUM_TYPENAME_ILLread_lp_state_value (state, &d);
+ ILL_BREAK_BODY_IF (rval);
+
+ rval = EGLPNUM_TYPENAME_QSnew_row (p, d, sense, rowname);
+ if (rval != 0)
+ {
+ QSlog("could not add row");
+ }
+ else
+ {
+ ILLsymboltab_register (&lp->rowtab, rname, &ind, &hit);
+ }
+CLEANUP:
+ ILL_IFFREE (rowname, char);
+}
+#endif
+#endif
+
+static int del_row_or_col (
+ EGLPNUM_TYPENAME_QSdata * p,
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ int isRow)
+{
+ int i[1], rval = 0;
+ char **names = (isRow) ? p->qslp->rownames : p->qslp->colnames;
+ int nnames = (isRow) ? p->qslp->nrows : p->qslp->nstruct;
+ ILLsymboltab *tab = (isRow) ? &lp->rowtab : &lp->coltab;
+
+ rval = EGLPNUM_TYPENAME_ILLread_lp_state_next_field_on_line (state);
+ ILL_BREAK_BODY_IF (rval);
+
+ i[0] = ILLutil_array_index (names, nnames, state->field);
+ if (i[0] >= 0)
+ {
+ rval = (isRow) ? EGLPNUM_TYPENAME_QSdelete_rows (p, 1, i) : EGLPNUM_TYPENAME_QSdelete_cols (p, 1, i);
+ if (rval == 0)
+ {
+ ILLsymboltab_delete (tab, state->field);
+ }
+ }
+ else
+ {
+ rval = EGLPNUM_TYPENAME_ILLlp_error (state, "\"%s\" is not defined.\n", state->field);
+ }
+
+CLEANUP:
+ ILL_RESULT (rval, "del_row_or_col");
+}
+
+static void del_row (
+ EGLPNUM_TYPENAME_QSdata * p,
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+ int rval = del_row_or_col (p, lp, state, 1);
+
+ if (rval == 0)
+ {
+ lp->nrows--;
+ }
+}
+
+static void del_col (
+ EGLPNUM_TYPENAME_QSdata * p,
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+ int rval = del_row_or_col (p, lp, state, 0);
+
+ if (rval == 0)
+ {
+ lp->ncols--;
+ }
+}
diff --git a/qsopt_ex/editor.h b/qsopt_ex/editor.h
new file mode 100644
index 0000000..227846a
--- /dev/null
+++ b/qsopt_ex/editor.h
@@ -0,0 +1,35 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCSINFO $Id: editor_EGLPNUM_TYPENAME.h,v 1.2 2003/11/05 16:57:39 meven Exp $ */
+#ifndef EGLPNUM_TYPENAME_EDITOR_H
+#define EGLPNUM_TYPENAME_EDITOR_H
+
+extern void EGLPNUM_TYPENAME_ILLeditor_init (
+ void);
+extern void EGLPNUM_TYPENAME_ILLeditor (
+ EGLPNUM_TYPENAME_QSdata * p);
+extern int EGLPNUM_TYPENAME_ILLeditor_solve (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int salgo);
+
+#endif
diff --git a/qsopt_ex/eg_elist.h b/qsopt_ex/eg_elist.h
new file mode 100644
index 0000000..ef584d7
--- /dev/null
+++ b/qsopt_ex/eg_elist.h
@@ -0,0 +1,229 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ *
+ * 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
+ * */
+/* ========================================================================= */
+/** @defgroup EGeList EGeList
+ *
+ * Here we define the basic interface for a circular linked list where the list
+ * is embeded in some other structure. The ideas come from the Linux Kernel
+ * implementation of lists. This implementation is based on the philosophy of
+ * embeded structures.
+ *
+ *
+ * @version 0.0.1
+ * @par History:
+ * - 2005-08-19
+ * - Add debugging control
+ * - 2005-05-23
+ * - First Implementation.
+ *
+ * @note In general, the functions described bellow don't perform consistency
+ * checks. It is asumed that the user does know what is he doing.
+ *
+ * @note If you want to have some debugging control try changing the debug level
+ * at compile time, and lowering the debug level asociated to the list function
+ * as defined in eg_configure.h.
+ *
+ * */
+/** @file
+ * @ingroup EGeList */
+/** @addtogroup EGeList */
+/** @{ */
+/** @example eg_elist.ex.c
+ * This is a working (althought useless) example on @ref EGeList.
+ * */
+/* ========================================================================= */
+#ifndef __EG_ELIST_H__
+#define __EG_ELIST_H__
+
+#include "eg_macros.h"
+
+/* ========================================================================= */
+/** @brief debug level for lists */
+#define __EL_DEBUG_ 100
+/* ========================================================================= */
+/** @brief Null-initialized embeded list */
+#define EGeListNull ((EGeList_t){0,0})
+
+/* ========================================================================= */
+/**
+ * @brief List Node Structure.
+ * @par Description:
+ * This structure is to store a general node of the list. It is composed by
+ * two members, that point to the next and previous structures in the list. */
+typedef struct EGeList_t
+{
+ struct EGeList_t *next;/**< Pointer to the next structure in the list */
+ struct EGeList_t *prev;/**< Pointer to the previous structure in the list */
+}
+EGeList_t;
+
+/* ========================================================================= */
+/** @brief Initialize a given structure to point to itself (in circular
+ * fashion).
+ * @param __lpt pointer to the list to initialize.
+ * @return the pointer to the list. */
+#define EGeListInit(__lpt) ({\
+ EGeList_t*const __EGeL_init =(__lpt);\
+ __EGeL_init->next = __EGeL_init->prev = __EGeL_init;})
+
+/* ========================================================================= */
+/** @brief Insert a __newpt __entry between two known consecutive entries.
+ * @par Description:
+ * This is only for internal list manipulation, where we know the prev/next
+ * entries already.
+ * @param __newpt pointer to the list node to insert.
+ * @param __prevpt pointer to the node to preceed the __newpt node.
+ * @param __nextpt pointer to the node to follow the __newpt node.
+ * @return the address of __newpt.
+ * */
+#define __EGeListAdd(__newpt,__prevpt,__nextpt) ({\
+ EGeList_t*const __EGeL_add_new = (__newpt);\
+ EGeList_t*const __EGeL_add_prev = (__prevpt);\
+ EGeList_t*const __EGeL_add_next = (__nextpt);\
+ __EGeL_add_next->prev = __EGeL_add_new;\
+ __EGeL_add_prev->next = __EGeL_add_new;\
+ __EGeL_add_new->next = __EGeL_add_next;\
+ __EGeL_add_new->prev = __EGeL_add_prev;\
+ __EGeL_add_new;})
+
+/* ========================================================================= */
+/** @brief Insert a __newpt __entry after the given pointer.
+ * @param __newpt pointer to the __newpt list node to insert.
+ * @param __head pointer from where the __newpt __entry will follow.
+ * @return the pointer to the __newpt __entry in the list.
+ * */
+#define EGeListAddAfter(__newpt,__head) __EGeListAdd(__newpt,__head,(__head)->next)
+
+/* ========================================================================= */
+/** @brief Insert a __newpt __entry before the given pointer.
+ * @param __newpt pointer to the __newpt list node to insert.
+ * @param __tailpt pointer that will follow the __newpt __entry in the list.
+ * @return the pointer to the __newpt __entry in the list.
+ * */
+#define EGeListAddBefore(__newpt,__tailpt) __EGeListAdd(__newpt,(__tailpt)->prev,__tailpt)
+
+/* ========================================================================= */
+/** @brief Given two nodes, link them as if they would follow one another in the
+ * list (used to delete points from a list).
+ * @param __prevpt pointer to the guy to be in first in the list.
+ * @param __nextpt pointer to the guy to follow in the list.
+ * @par Description:
+ * This function is intended to be used only internally, where we know what is
+ * what, if you use it is because you also know what is going on.
+ * */
+#define __EGeListLink(__prevpt,__nextpt) ({\
+ EGeList_t* __EGeL_lnk_prev = (__prevpt);\
+ EGeList_t* __EGeL_lnk_next = (__nextpt);\
+ __EGeL_lnk_prev->next = __EGeL_lnk_next;\
+ __EGeL_lnk_next->prev = __EGeL_lnk_prev;\
+ 0;})
+
+/* ========================================================================= */
+/** @brief Given a node, eliminate it from the list it bellongs. but don't
+ * change the internal data in the eliminated list (be carefull, if you will
+ * use it afterwards, then you MUST initialize it). If debugging is enabled,
+ * then whenever you delete, the connector is reseted to 0xffffffff. What you
+ * can count on is that the connector won't be NULL after deleting it from the
+ * list, but it's values may be lost if we are debugging.
+ * @param __entry __entry to eliminate from the list.
+ * @return pointer to the deleted __entry from the list.*/
+#define EGeListDel(__entry) ({\
+ EGeList_t *const __EGeL_del_entr = (__entry);\
+ __EGeListLink(__EGeL_del_entr->prev,__EGeL_del_entr->next);\
+ if(__EL_DEBUG_ <= DEBUG) \
+ (*__EGeL_del_entr) = (EGeList_t){(EGeList_t*)0xffffffffU,\
+ (EGeList_t*)0xffffffffU};\
+ __EGeL_del_entr;})
+
+/* ========================================================================= */
+/** @brief Replace one __entry with another in a list.
+ * @param __oldpt __entry to be replaced, note that the pointers stored in next/prev
+ * won't be changed, this may possible lead to errors if the __entry is used
+ * afterwards without initialization.
+ * @param __newpt __newpt __entry in the list.
+ * @return pointer to the old replaced member.
+ * */
+#define EGeListReplace(__oldpt,__newpt) ({\
+ EGeList_t* __EGeL_rep_old = (__oldpt);\
+ EGeList_t* __EGeL_rep_new = (__newpt);\
+ __EGeL_rep_new->next = __EGeL_rep_old->next;\
+ __EGeL_rep_new->prev = __EGeL_rep_old->prev;\
+ __EGeL_rep_new->next->prev = __EGeL_rep_new;\
+ __EGeL_rep_new->prev->next = __EGeL_rep_new;\
+ __EGeL_rep_old;})
+
+/* ========================================================================= */
+/** @brief Move an element from one list to another (deleting it from the
+ * original one).
+ * @param __entry element to be removed from it's current list to a position
+ * after the given __head.
+ * @param __head element to be before the moved element.
+ * */
+#define EGeListMoveAfter(__entry,__head) ({\
+ __EGeListLink((__entry)->prev,(__entry)->next);\
+ EGeListAddAfter(__entry,__head);})
+
+/* ========================================================================= */
+/** @brief Move an element from one list to another (deleting it from the
+ * original one).
+ * @param __entry element to be removed from it's current list to a position
+ * before the given __tailpt.
+ * @param __tailpt element to be after the moved element.
+ * */
+#define EGeListMoveBefore(__entry,__tailpt) ({\
+ __EGeListLink((__entry)->prev,(__entry)->next);\
+ EGeListAddBefore(__entry,__tailpt);})
+
+/* ========================================================================= */
+/** @brief test whether a list is empty (i.e. he is its own next pointer) */
+#define EGeListIsEmpty(__head) ({\
+ EGeList_t* __EGeL_emp_head = (__head);\
+ (__EGeL_emp_head == __EGeL_emp_head->next);})
+
+/* ========================================================================= */
+/** @brief move all elements in one list to the given location in a second list.
+ * Note that this function assumes that the list is represented by a pointer to
+ * an EGeList_t structure that act as a marker but that don't bellong to the
+ * list, and thus is not included in the joinded list.
+ * @param __list marker to the list to be joined with the second. Note that the
+ * fields in list won't be reinitialized, so be carefull with that, because the
+ * fields are pointing to inconsistent data as it is, if you want to reutilize
+ * the list you must call #EGeListInit before.
+ * @param __head position from where the list will be spliced in.
+ * @note Note that the original list is left in an undefined status, so before
+ * use it, it should be re-initialized.
+ * */
+#define __EGeListSplice(__list,__head) ({\
+ EGeList_t* __EGeL_spl_list = (__list);\
+ EGeList_t* __EGeL_spl_first = __EGeL_spl_list->next;\
+ EGeList_t* __EGeL_spl_last = __EGeL_spl_list->prev;\
+ EGeList_t* __EGeL_spl_head = (__head);\
+ EGeList_t* __EGeL_spl_at = __EGeL_spl_head->next;\
+ __EGeL_spl_first->prev = __EGeL_spl_head;\
+ __EGeL_spl_head->next = __EGeL_spl_first;\
+ __EGeL_spl_last->next = __EGeL_spl_at;\
+ __EGeL_spl_at->prev = __EGeL_spl_last;\
+ 0;})
+#define EGeListSplice(__list,__head) ({if(!EGeListIsEmpty(__list)) __EGeListSplice(__list,__head);})
+
+/* ========================================================================= */
+/** @}*/
+/* end of eg_elist.h */
+#endif
diff --git a/qsopt_ex/eg_exact.h b/qsopt_ex/eg_exact.h
new file mode 100644
index 0000000..a8d436d
--- /dev/null
+++ b/qsopt_ex/eg_exact.h
@@ -0,0 +1,41 @@
+/* QSopt-Exact "An exact LP solver"
+ *
+ * Copyright (C) 2006 Daniel Espinoza.
+ *
+ * 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
+ * */
+/* ========================================================================= */
+/** @mainpage QSopt-Exact Home Page
+ *
+ * @section Introduction
+
+<P>This is a joint project of <A HREF=http://www.dii.uchile.cl/~daespino TARGET=_top>Daniel Espinoza</A>, <A HREF=http://www.isye.gatech.edu/~wcook TARGET=_top>William Cook</A>, <A HREF=http://www.research.ibm.com/people/s/sanjeebd TARGET=_top>Sanjeeb Dash</A> and <A HREF=http://public.research.att.com/viewPage.cfm?PageID=424 TARGET=_top>David Applegate</A>.
+Also, <A HREF=http://www.zib.de/wolter/ TARGET=_top>Kati Wolter</A> has contributed with bug-fixes, bug-reports and special functionality for SCIP exact.</P>
+
+<P>The objective of this software is to provide a solver for Linear Programming (and Integer Programming to a lesser degree) that returns true (rational) optimal solutions.</P>
+
+<P>It relies heavilly on the <A HREF=http://www.swox.com/gmp TARGET=_top>GNUMP library</A>, that provides a multiprecision library for both floating point and also rational arithmetic.
+Note that if you use a dynamicly linked version of QSopt-Exact, then the GMP library should have been compiled with the option --enable-alloca=malloc-reentrant, this is needed to avoid memory corruption.
+The basis for the LP solver was taken from <A HREF=http://www.isye.gatech.edu/~wcook/qsopt TARGET=_top>QSopt</A>, which is an LP solver based on floating point arithmetic and available for free for research purposes.
+A brief description of the implementation and the obtained results can be obtained <A HREF=http://www.dii.uchile.cl/~daespino/files/exact_simplex.pdf >here (pdf)</A>, and a longer description (which is part of my Ph.D. thesis) can be found <A HREF=http://www.dii.uchile.cl/~daespino/files/espinoza_daniel_g_200605_phd.pdf >here</A>
+Much of the functionality used in QSopt-Exact comes from <A HREF=http://www.dii.uchile.cl/~daespino/EGlib_doc/main.html TARGET=_self>EGlib</A>.
+</P>
+
+<P>You can see the <A HREF=http://www.dii.uchile.cl/~daespino/QSoptExact_doc/modules.html TARGET=_self>documentation</A> or download the <A HREF=http://www.dii.uchile.cl/~daespino/SOurce/QSoptExact.tar.bz2 TARGET=_top>program source</A>.</P>
+<P>We also have made available binaries for <A HREF=http://www.dii.uchile.cl/~daespino/SOurce/QSoptExact-32.tar.bz2 TARGET=_top>linux 32 bit</A> and for <A HREF=http://www.dii.uchile.cl/~daespino/SOurce/QSoptExact-64.tar.bz2 TARGET=_top>linux 64 bit</A>
+
+<P>Finally, many thanks to all people that have contributed with bug-reports, comments, and help.</P>
+
+ * */
diff --git a/qsopt_ex/eg_exutil.c b/qsopt_ex/eg_exutil.c
new file mode 100644
index 0000000..5491b0d
--- /dev/null
+++ b/qsopt_ex/eg_exutil.c
@@ -0,0 +1,485 @@
+/* ========================================================================= */
+/* ESolver "Exact Mixed Integer Linear Solver" provides some basic structures
+ * and algorithms commons in solving MIP's
+ *
+ * Copyright (C) 2005 Daniel Espinoza.
+ *
+ * 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
+ * */
+/* ========================================================================= */
+/** @file
+ * @ingroup Esolver */
+/** @addtogroup Esolver */
+/** @{ */
+#include "eg_exutil.h"
+
+#include "logging-private.h"
+
+/* ========================================================================= */
+/** @name EXutilStatics
+ * Variables asociated with the #EXutilApproximate function, we use them
+ * as static to save some time in intialization */
+/*@{*/
+/** @brief Array of integers used in the continued fraction method */
+static mpz_t Z[7];
+/**@brief rational remainder used in the continued fraction method */
+static mpq_t cvl;
+/* ========================================================================= */
+/** @brief Initialize the static variables at start-up */
+void EXutilDoInit (void)
+{
+ unsigned __EXui;
+ EGlpNumStart();
+ mpq_init (cvl);
+ for (__EXui = 7; __EXui--;)
+ mpz_init (Z[__EXui]);
+}
+
+/* ========================================================================= */
+/** @brief Clear all memory related to the static variables */
+void EXutilDoClear (void)
+{
+ unsigned __EXui;
+ mpq_clear (cvl);
+ for (__EXui = 7; __EXui--;)
+ mpz_clear (Z[__EXui]);
+ EGlpNumClear();
+
+}
+
+/*@}*/
+
+/* ========================================================================= */
+int EXutilIntegralize (const unsigned n,
+ mpq_t * const a,
+ mpq_t b,
+ mpq_t maxabs)
+{
+ mpz_t lcm,
+ gcd;
+ register unsigned int i;
+ mpz_init (lcm);
+ mpz_init (gcd);
+ mpz_set (lcm, mpq_denref (b));
+ mpz_set (gcd, mpq_numref (b));
+ if (mpz_cmp_ui (gcd, 0UL) == 0)
+ mpz_set_ui (gcd, 1UL);
+ /* compute the greatest common divisor ammong the numerator of a_i and b,
+ * and the least common multiple ammong the denominators of a_i and b */
+ for (i = n; i--;)
+ {
+ mpz_lcm (lcm, lcm, mpq_denref (a[i]));
+ mpz_gcd (gcd, gcd, mpq_numref (a[i]));
+ }
+ /* divide everything by lcm/gcd */
+ mpz_mul (mpq_numref (b), mpq_numref (b), lcm);
+ mpz_mul (mpq_denref (b), mpq_denref (b), gcd);
+ mpq_canonicalize (b);
+ mpz_abs (mpq_numref (maxabs), mpq_numref (b));
+ for (i = n; i--;)
+ {
+ mpz_mul (mpq_denref (a[i]), mpq_denref (a[i]), gcd);
+ mpz_mul (mpq_numref (a[i]), mpq_numref (a[i]), lcm);
+ mpq_canonicalize (a[i]);
+ if (mpz_cmpabs (mpq_numref (maxabs), mpq_numref (a[i])) < 0)
+ mpz_abs (mpq_numref (maxabs), mpq_numref (a[i]));
+ }
+ /* ending */
+ mpz_set_ui (mpq_denref (maxabs), 1UL);
+ mpz_clear (gcd);
+ mpz_clear (lcm);
+ return 0;
+}
+
+/* ========================================================================= */
+int EXutilSimplify (const unsigned n,
+ mpq_t * const a,
+ mpq_t b)
+{
+ register unsigned i;
+ mpq_t maxabs;
+ mpq_init (maxabs);
+ EXutilIntegralize (n, a, b, maxabs);
+ /* normalize the cut so that |(a,b)|_inf == 1 */
+ if (mpz_cmp_ui (mpq_numref (maxabs), 0UL))
+ {
+ mpq_div (b, b, maxabs);
+ for (i = n; i--;)
+ mpq_div (a[i], a[i], maxabs);
+ }
+ /* ending */
+ mpq_clear (maxabs);
+ return 0;
+}
+
+/* ========================================================================= */
+void mpq_GomoryCoeff (mpq_t rop,
+ mpq_t coef,
+ unsigned const is_int,
+ int const bound,
+ unsigned const cut_mlt,
+ mpq_t b_frac)
+{
+ mpq_t fj;
+ mpq_init (fj);
+ mpq_set_ui (rop, 0UL,1UL);
+ /* if the variable is integer */
+ if (is_int)
+ {
+ if (mpq_IsInteger (coef))
+ {
+ mpq_set (rop, coef);
+ mpq_EGlpNumMultUiTo (rop, cut_mlt);
+ mpq_EGlpNumMultTo (rop, b_frac);
+ }
+ /* if the variable is integer, but the coefficient id fractional */
+ else
+ {
+ mpq_set (fj, coef);
+ mpq_EGlpNumMultUiTo (fj, cut_mlt);
+ mpq_FracPart (fj, fj);
+ /* if the variable is complemented to its lower bound */
+ if (bound == 'L')
+ {
+ if (mpq_cmp (fj, b_frac) <= 0)
+ {
+ mpq_set (rop, coef);
+ mpq_EGlpNumMultUiTo (rop, cut_mlt);
+ mpq_EGlpNumFloor (rop, rop);
+ mpq_EGlpNumMultTo (rop, b_frac);
+ mpq_EGlpNumAddTo (rop, fj);
+ }
+ else
+ {
+ mpq_set (rop, coef);
+ mpq_EGlpNumMultUiTo (rop, cut_mlt);
+ mpq_EGlpNumCeil (rop, rop);
+ mpq_EGlpNumMultTo (rop, b_frac);
+ }
+ }
+ /* if the variable is complemented to its upper bound */
+ else
+ {
+ mpq_EGlpNumSubTo (fj, mpq_oneLpNum);
+ mpq_neg (fj, fj);
+ if (mpq_cmp (fj, b_frac) <= 0)
+ {
+ mpq_set (rop, coef);
+ mpq_EGlpNumMultUiTo (rop, cut_mlt);
+ mpq_EGlpNumCeil (rop, rop);
+ mpq_EGlpNumMultTo (rop, b_frac);
+ mpq_EGlpNumSubTo (rop, fj);
+ }
+ else
+ {
+ mpq_set (rop, coef);
+ mpq_EGlpNumMultUiTo (rop, cut_mlt);
+ mpq_EGlpNumFloor (rop, rop);
+ mpq_EGlpNumMultTo (rop, b_frac);
+ }
+ }
+ }
+ }
+ /* if the variable is continuous */
+ else
+ {
+ /* if the variable is complemented to its lower bound */
+ if (bound == 'L')
+ {
+ if (mpq_cmp_ui (coef, 0UL,1UL) > 0)
+ {
+ mpq_set (rop, coef);
+ mpq_EGlpNumMultUiTo (rop, cut_mlt);
+ }
+ }
+ /* if the variable is complemented to its upper bound */
+ else
+ {
+ if (mpq_cmp_ui (coef, 0UL,1UL) < 0)
+ {
+ mpq_set (rop, coef);
+ mpq_EGlpNumMultUiTo (rop, cut_mlt);
+ }
+ }
+ }
+ /* done */
+ mpq_clear (fj);
+}
+
+/* ========================================================================= */
+int EXutilExpandLogicals (mpq_QSdata * const act_lp,
+ mpq_t * const vector,
+ mpq_t b,
+ mpq_ILLlp_rows * const lprows)
+{
+ const int n_rows = act_lp->qslp->nrows;
+ const int n_struct = act_lp->qslp->nstruct;
+ int const *const rowmap = act_lp->qslp->rowmap;
+ mpq_t * const rhs = act_lp->qslp->rhs;
+ mpq_ILLmatrix *const A = &(act_lp->qslp->A);
+ int rowbeg;
+ int rowcnt;
+ int *rowind;
+ mpq_t * rowval;
+ register int i,
+ k;
+ for (i = n_rows; i--;)
+ {
+ /* convert the vector */
+ if (mpz_cmp_ui (mpq_numref (vector[i + n_struct]), 0UL))
+ {
+ rowbeg = lprows->rowbeg[i];
+ rowcnt = lprows->rowcnt[i];
+ rowind = lprows->rowind + rowbeg;
+ rowval = lprows->rowval + rowbeg;
+ /* we use slack again as the multiplier that we need to add the
+ * row to the current vector so as to make dissapear the slack */
+ mpq_neg (cvl, vector[i + n_struct]);
+ mpq_div (cvl, cvl, A->matval[A->matbeg[rowmap[i]]]);
+ MESSAGE (EX_UTIL_VERBOSE + 100, "Replacing constraint %s with multiple"
+ " %lf from integer part", act_lp->qslp->rownames[i],
+ mpq_get_d (cvl));
+ mpq_EGlpNumAddInnProdTo (b, rhs[i], cvl);
+ for (k = rowcnt; k--;)
+ mpq_EGlpNumAddInnProdTo (vector[rowind[k]], cvl, rowval[k]);
+ mpq_set_ui (vector[i + n_struct], 0UL, 1UL);
+ }
+ }
+ return 0;
+}
+
+/* ========================================================================= */
+void EXutilApproximate (mpq_t var,
+ mpq_t ori,
+ unsigned const max_den)
+{
+ /* local variables */
+ unsigned lsng = mpz_cmp_ui (mpq_numref (ori), 0UL) < 0 ? 1U : 0U;
+ int i;
+ mpq_t __lpnum__;
+ mpq_init(__lpnum__);
+ /* check if the given number is zero, if so, set to zero var and return */
+ if (mpz_cmp_ui (mpq_numref (ori), 0UL) == 0)
+ {
+ return;
+ }
+ /* if not, then we have some work to do */
+ /* now we initialize the internal numbers */
+ mpq_abs (cvl, ori);
+ for (i = 7; i--;)
+ mpz_set_ui (Z[i], 0UL);
+ mpz_set_ui (Z[0], 1UL);
+ mpz_set_ui (Z[4], 1UL);
+ mpz_fdiv_q (Z[1], mpq_numref (cvl), mpq_denref (cvl));
+ mpq_set_z (__lpnum__, Z[1]);
+ mpq_sub (cvl, cvl, __lpnum__);
+ /* now we loop until the next t's is more than mpf_eps */
+ /* the formula is
+ * p_i = t_i*p_{i-1} + p_{i-2}, and
+ * q_i = t_i*q_{i-1} + q_{i-2}
+ * note that |x-p_i/q_i|<1/q_i^2
+ * for us t_i = Z[6], and the current number is either [0,1,2] in the Z
+ * array, we use those popsitions ciclicly, and use the four position as a
+ * temporary number, Z+4 is used to store q's, at the beginning i = 1. */
+ while (1)
+ {
+ if (mpq_cmp_ui (cvl, 1UL, (unsigned long)max_den) < 0 || (mpz_cmp_ui (Z[4], (unsigned long)max_den) > 0))
+ {
+ mpz_set (mpq_denref (var), Z[4]);
+ mpz_set (mpq_numref (var), Z[1]);
+ break;
+ }
+ /* first run */
+ mpq_inv (cvl, cvl);
+ mpz_fdiv_q (Z[6], mpq_numref (cvl), mpq_denref (cvl));
+ mpq_set_z (__lpnum__, Z[6]);
+ mpq_sub (cvl, cvl, __lpnum__);
+ mpz_set (Z[2], Z[0]);
+ mpz_addmul (Z[2], Z[1], Z[6]);
+ mpz_set (Z[5], Z[3]);
+ mpz_addmul (Z[5], Z[4], Z[6]);
+ if (mpq_cmp_ui (cvl, 1UL, (unsigned long)max_den) < 0 || (mpz_cmp_ui (Z[5], (unsigned long)max_den) > 0))
+ {
+ mpz_set (mpq_denref (var), Z[5]);
+ mpz_set (mpq_numref (var), Z[2]);
+ break;
+ }
+ /* second run */
+ mpq_inv (cvl, cvl);
+ mpz_fdiv_q (Z[6], mpq_numref (cvl), mpq_denref (cvl));
+ mpq_set_z (__lpnum__, Z[6]);
+ mpq_sub (cvl, cvl, __lpnum__);
+ mpz_set (Z[0], Z[1]);
+ mpz_addmul (Z[0], Z[2], Z[6]);
+ mpz_set (Z[3], Z[4]);
+ mpz_addmul (Z[3], Z[5], Z[6]);
+ if (mpq_cmp_ui (cvl, 1UL, (unsigned long)max_den) < 0 || (mpz_cmp_ui (Z[3], (unsigned long)max_den) > 0))
+ {
+ mpz_set (mpq_denref (var), Z[3]);
+ mpz_set (mpq_numref (var), Z[0]);
+ break;
+ }
+ /* third run */
+ mpq_inv (cvl, cvl);
+ mpz_fdiv_q (Z[6], mpq_numref (cvl), mpq_denref (cvl));
+ mpq_set_z (__lpnum__, Z[6]);
+ mpq_sub (cvl, cvl, __lpnum__);
+ mpz_set (Z[1], Z[2]);
+ mpz_addmul (Z[1], Z[0], Z[6]);
+ mpz_set (Z[4], Z[5]);
+ mpz_addmul (Z[4], Z[3], Z[6]);
+ }
+ /* ending */
+ mpq_canonicalize (var);
+ if (lsng)
+ mpq_neg (var, var);
+ /* clean-up */
+ mpq_clear(__lpnum__);
+ return;
+}
+
+/* ========================================================================= */
+void EXutilOverEstimate (mpq_t var,
+ mpq_t ori,
+ unsigned const max_den)
+{
+ EXutilApproximate (var, ori, max_den);
+ /* check if var is < ori, if so, we must add one to the numerator */
+ if (mpq_cmp (ori, var) > 0)
+ {
+ mpq_set_ui (cvl, 1UL, (unsigned long)(max_den * max_den));
+ mpq_add (var, var, cvl);
+ EXIT (mpq_cmp (ori, var) > 0, "Imposible!");
+ }
+ return;
+}
+
+/* ========================================================================= */
+void EXutilNicefy (mpq_QSdata * const act_prob,
+ const unsigned char *const var_stat,
+ const unsigned max_den,
+ mpq_t * a,
+ mpq_t b,
+ int const sense)
+{
+ const unsigned square = max_den * max_den;
+ const int nstruct = act_prob->qslp->nstruct;
+ const int *const structmap = act_prob->qslp->structmap;
+ mpq_t *const lower = act_prob->qslp->lower;
+ mpq_t *const upper = act_prob->qslp->upper;
+ mpq_t num1,
+ num2;
+ register int i;
+ int colid = 0;
+ int sign = 0;
+ unsigned cur_stat = 0;
+ mpq_init (num1);
+ mpq_init (num2);
+ if (sense != 'L' && sense != 'G')
+ return;
+ /* we internally assume that the inequality is of the form ax >= b */
+ if (sense == 'L')
+ {
+ mpq_neg (b, b);
+ for (i = nstruct; i--;)
+ mpq_neg (a[i], a[i]);
+ }
+ /* now we first approximate each coefficient */
+ for (i = nstruct; i--;)
+ {
+ colid = structmap[i];
+ cur_stat = var_stat[colid];
+ /* if the variables is not bounded, we can't nicefy the coefficient */
+ if ((cur_stat & (EX_STATUS_UB | EX_STATUS_LB)) == 0)
+ continue;
+ /* if the numerator is less than square, there is nothing to do */
+ if (mpz_cmp_ui (mpq_denref (a[i]), (unsigned long)square) <= 0)
+ continue;
+ EXutilApproximate (num1, a[i], max_den);
+ mpq_sub (num2, num1, a[i]);
+ sign = mpz_cmp_ui (mpq_numref (num2), 0UL);
+ /* depending on the side that the approximation land we see what we have to
+ * do, first case, num1 > a[i] */
+ REDO:
+ if (sign > 0)
+ {
+ /* if the variable is bounded bellow, we just update the RHS and set the
+ * coefficient */
+ if (cur_stat & EX_STATUS_LB)
+ {
+ EXIT ((mpq_EGlpNumIsEqqual (lower[colid], mpq_ILL_MINDOUBLE)),
+ "Imposible");
+ mpq_EGlpNumAddInnProdTo (b, num2, lower[colid]);
+ mpq_set (a[i], num1);
+ }
+ /* otherwise, we can't approximate by above, but we have to approximate
+ * by bellow */
+ else
+ {
+ mpq_set_ui (num2, 1UL, (unsigned long)square);
+ mpq_sub (num1, num1, num2);
+ mpq_sub (num2, num1, a[i]);
+ sign = mpz_cmp_ui (mpq_numref (num2), 0UL);
+ goto REDO;
+ }
+ }
+ /* otherwise, we have that num1 < a[i] */
+ else if (sign < 0)
+ {
+ /* if the variable is bounded by above, we just update the RHS and set
+ * the coefficient */
+ if (cur_stat & EX_STATUS_UB)
+ {
+ EXIT ((mpq_EGlpNumIsEqqual (upper[colid], mpq_ILL_MAXDOUBLE)),
+ "Imposible");
+ mpq_EGlpNumAddInnProdTo (b, num2, upper[colid]);
+ mpq_set (a[i], num1);
+ }
+ /* otherwise, we can't approximate by bellow, but we have to approximate
+ * by above. */
+ else
+ {
+ mpq_set_ui (num2, 1UL, (unsigned long)square);
+ mpq_add (num1, num1, num2);
+ mpq_sub (num2, num1, a[i]);
+ sign = mpz_cmp_ui (mpq_numref (num2), 0UL);
+ goto REDO;
+ }
+ }
+ }
+ /* now we round the RHS, we do this by adding the constraint 0 >= -1 */
+ EXutilApproximate (num1, b, max_den);
+ if (mpq_cmp (num1, b) > 0)
+ {
+ mpq_set_ui (num2, 1UL, (unsigned long)square);
+ mpq_sub (num1, num1, num2);
+ }
+ mpq_set (b, num1);
+ /* before ending, we return the constraint to its normal form */
+ if (sense == 'L')
+ {
+ mpq_neg (b, b);
+ for (i = nstruct; i--;)
+ mpq_neg (a[i], a[i]);
+ }
+ /* ending */
+ mpq_clear (num2);
+ mpq_clear (num1);
+ return;
+}
+
+/* ========================================================================= */
+/** @} */
+/* end eg_exutil.c */
diff --git a/qsopt_ex/eg_exutil.h b/qsopt_ex/eg_exutil.h
new file mode 100644
index 0000000..7855184
--- /dev/null
+++ b/qsopt_ex/eg_exutil.h
@@ -0,0 +1,317 @@
+/* ========================================================================= */
+/* ESolver "Exact Mixed Integer Linear Solver" provides some basic structures
+ * and algorithms commons in solving MIP's
+ *
+ * Copyright (C) 2005 Daniel Espinoza.
+ *
+ * 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
+ * */
+/* ========================================================================= */
+#ifndef __EG_EX_UTIL__
+#define __EG_EX_UTIL__
+
+#include <stdlib.h>
+
+#include "eg_lpnum.h"
+#include "eg_io.h"
+
+#include "qstruct_mpq.h"
+#include "lpdata_mpq.h"
+
+/** @file
+ * @ingroup Esolver */
+/** @addtogroup Esolver */
+/** @{ */
+/* ========================================================================= */
+/** @brief status for variables that are logicals */
+#define EX_STATUS_LGC 1U
+
+/* ========================================================================= */
+/** @brief status for variables that are structural */
+#define EX_STATUS_STR 2U
+
+/* ========================================================================= */
+/** @brief status for variables that are integer */
+#define EX_STATUS_INT 4U
+
+/* ========================================================================= */
+/** @brief status for variables that bounded from below */
+#define EX_STATUS_LB 8U
+
+/* ========================================================================= */
+/** @brief status for variables that bounded from above */
+#define EX_STATUS_UB 16U
+
+/* ========================================================================= */
+/** @brief status for integer variable fixed at its upper bound. This status is
+ * not defined while calling cut callbacks. */
+#define EX_STATUS_FIX_UB 32U
+
+/* ========================================================================= */
+/** @brief status for integer variable fixed at its lower bound. This status is
+ * not defined while calling cut callbacks. */
+#define EX_STATUS_FIX_LB 64U
+
+/* ========================================================================= */
+/** @brief status for integer variable among our set of selected integer
+ * variables. This status is not defined while calling cut callbacks. */
+#define EX_STATUS_BESTFRAC 128U
+
+/* ========================================================================= */
+/** @brief given a cut ax <=> b, write it in integer form ,i.e. set all a,b to
+ * integer in such a way that a_i and b are all relativelly prime.
+ * @param n size of the a vector.
+ * @param a RHS of the inequality
+ * @param b LHS of the inequality.
+ * @param maxabs return the maximum absolute value among all resulting a_i,b.
+ * @return zero on success, non-zero otherwise.
+ * */
+int EXutilIntegralize (const unsigned n,
+ mpq_t * const a,
+ mpq_t b,
+ mpq_t maxabs);
+
+/* ========================================================================= */
+/** @brief verbosity level */
+#define EX_UTIL_VERBOSE 100
+
+/* ========================================================================= */
+/** @brief given two vectors (a,b) and (v,w), compute its inner product and
+ * store it into rop.
+ * @param dim dimmension of the a and v part of the vector.
+ * @param a first part of the first vector.
+ * @param b second part of the first vector.
+ * @param v first part of the second vector.
+ * @param w second part of the second vector.
+ * @param rop where we store the result.
+ * @note we may take a == v and/or b == w.
+ * */
+#define EXutilInnProd(dim,a,b,v,w,rop) do{\
+ register unsigned __EXuti = (dim);\
+ mpq_mul(rop,b,w);\
+ while(__EXuti--) mpq_EGlpNumAddInnProdTo(rop,(a)[__EXuti],(v)[__EXuti]);\
+ } while(0);
+
+/* ========================================================================= */
+/** @brief Compute the number of non-zeros in a given vector.
+ * @param dim size of the a vector.
+ * @param a vector where we are operating.
+ * @param rop where to return the number of non-zeros (it should be an integer
+ * variable, not a pointer to such a variable) */
+#define EXutilNzSz(dim,a,rop) do{\
+ register unsigned __EXuti = (dim);\
+ rop = 0;\
+ while(__EXuti--) if(mpz_cmp_ui(mpq_numref((a)[__EXuti]),0UL)) rop++;}while(0)
+
+/* ========================================================================= */
+/** @brief Compute the L_1 norm of a given vector.
+ * @param dim size of the a vector.
+ * @param a vector where we are operating.
+ * @param rop where to retirn the L1 norm value */
+#define EXutilL1Norm(dim,a,rop) do{\
+ mpq_t*const __EXuta = (a);\
+ mpq_t __qtmp__;\
+ register unsigned __EXuti = (dim);\
+ mpq_init(__qtmp__);\
+ mpq_set_ui(rop,0UL,1UL);\
+ while(__EXuti--){\
+ mpq_abs(__qtmp__,__EXuta[__EXuti]);\
+ mpq_add(rop,rop,__qtmp__);}mpq_clear(__qtmp__);}while(0)
+
+/* ========================================================================= */
+/** @brief given a cut ax <=> b, write it in normalized form ,i.e. set all a,b
+ * to integer in such a way that a_i and b are all relativelly prime, and
+ * divide them all over the
+ * maximum such (a_i,b) (so that the infinity norm of (a,b) is one.
+ * @param n size of the a vector.
+ * @param a RHS of the inequality
+ * @param b LHS of the inequality.
+ * @return zero on success, non-zero otherwise.
+ * */
+int EXutilSimplify (const unsigned n,
+ mpq_t * const a,
+ mpq_t b);
+
+/* ========================================================================= */
+/** @brief asign to the first number the fractional part of the second, i.e.
+ * \f$ rop = op1 - \lfloor op1 \rfloor \f$.
+ * @param rop where to retunr our result.
+ * @param op1 number for wich we want to compute its fractional part */
+#define mpq_FracPart(rop, op1) do{\
+ mpz_fdiv_r (mpq_numref (rop), mpq_numref (op1), mpq_denref (op1));\
+ mpz_set (mpq_denref (rop), mpq_denref (op1));\
+ mpq_canonicalize((rop));\
+} while(0)
+
+/* ========================================================================= */
+/** @brief test if the given number is integer.
+ * @param op number to test.
+ * @return one if the nummber is integer, zero- otherwise. */
+#define mpq_IsInteger(op) ({\
+ (mpz_cmp(mpq_denref(op),mpz_oneLpNum)==0);})
+
+/* ========================================================================= */
+/** @brief round to \f$-\infty\f$ the given number to the closest fraction
+ * of the form \f$a/2^{exp}\f$ from bellow.
+ * @param op number to round.
+ * @param exp exponent to use in the fraction */
+#define mpq_FroundExp(op,exp) do{\
+ mpz_t __ztmp__;\
+ mpz_init(__ztmp__);\
+ mpz_mul_2exp(__ztmp__,mpq_numref((op)),(exp));\
+ mpz_fdiv_q(mpq_numref((op)),__ztmp__,mpq_denref((op)));\
+ mpz_mul_2exp(mpq_denref((op)),mpz_oneLpNum,(exp));\
+ mpq_canonicalize((op));mpz_clear(__ztmp__);}while(0)
+
+/* ========================================================================= */
+/** @brief round to \f$+\infty\f$ the given number to the closest fraction
+ * of the form \f$a/2^{exp}\f$ from above.
+ * @param op number to round.
+ * @param exp exponent to use in the fraction */
+#define mpq_CroundExp(op,exp) do{\
+ mpz_t __ztmp__;\
+ mpz_init(__ztmp__);\
+ mpz_mul_2exp(__ztmp__,mpq_numref((op)),(exp));\
+ mpz_cdiv_q(mpq_numref((op)),__ztmp__,mpq_denref((op)));\
+ mpz_mul_2exp(mpq_denref((op)),mpz_oneLpNum,(exp));\
+ mpq_canonicalize((op));mpz_clear(__ztmp__);}while(0)
+
+/* ========================================================================= */
+/** @brief round to \f$0\f$ the given number to the closest fraction
+ * of the form \f$a/2^{exp}\f$ towards zero.
+ * @param op number to round.
+ * @param exp exponent to use in the fraction */
+#define mpq_TroundExp(op,exp) do{\
+ mpz_t __ztmp__;\
+ mpz_init(__ztmp__);\
+ mpz_mul_2exp(__ztmp__,mpq_numref((op)),(exp));\
+ mpz_tdiv_q(mpq_numref((op)),__ztmp__,mpq_denref((op)));\
+ mpz_mul_2exp(mpq_denref((op)),mpz_oneLpNum,(exp));\
+ mpq_canonicalize((op));mpz_clear(__ztmp__);}while(0)
+
+/* ========================================================================= */
+/** @brief compute the gomory coefficient of the variable given the original
+ * coefficient, the multiplier, and all relevant information.
+ * @param rop Where we return the gomory coefficient. (it should be different
+ * location than the original coefficient).
+ * @param coef original coefficient in the equality that we are using to
+ * derive the gomory cut.
+ * @param is_int this is either zero (indicating that the variable asociated
+ * with this coefficient is continuous) or one (indicating that the variable
+ * asociated with this coeffcient is integer).
+ * @param bound indicate if this variable was complemented to its lower bound
+ * (then L) or to its upper bound (then U), any other value will generate an
+ * error.
+ * @param cut_mlt multiplier to use to the coefficient (and thus the effective
+ * coefficient would be coef*cut_mlt).
+ * @param b_frac fractional part of the RHS in the equation (after
+ * complementing variables). */
+void mpq_GomoryCoeff (mpq_t rop,
+ mpq_t coef,
+ unsigned const is_int,
+ int const bound,
+ unsigned const cut_mlt,
+ mpq_t b_frac);
+
+/* ========================================================================= */
+/** @brief Given a vector in QSopt external form, and a row description of the
+ * related LP, re-write the vector using only real variables, we do that by
+ * substracting the equation defining the logical variable multiplied by the
+ * coefficient of the logical variable in the vector to the vector.
+ * @param act_lp lp where we are working.
+ * @param vector vector of length at least nrows + nstruct where we want to
+ * replace all logical coefficients.
+ * @param lprows row description of the given LP.
+ * @param rhs if we look at vector,rhs as an inequality, then we eliminate the
+ * slack coefficient form the inequality as a whole.
+ * @return zero on success, non-zero otherwise.
+ * */
+int EXutilExpandLogicals (mpq_QSdata * const act_lp,
+ mpq_t * const vector,
+ mpq_t rhs,
+ mpq_ILLlp_rows * const lprows);
+
+/* ========================================================================= */
+/** @brief Approximate <A HREF=http://mathworld.wolfram.com/ContinuedFraction.html TARGET=_top>using continued fractions method</A> a given rational
+ * \f$\frac{a}{b} \f$ with another rational \f$\frac{a'}{b'}\f$ that satisfy
+ * that \f$ b' < max_den^2 \f$ and also
+ * \f$|\frac{a}{b} - \frac{a'}{b'}|\leq\frac1{max_den^2}\f$.
+ * @param ori original coefficient that we want to represent as a/b with b <=
+ * max_den^2.
+ * @param dest we return here the resulting number.
+ * @param max_den maximum allowed denominator in the new representation. */
+void EXutilApproximate (mpq_t dest,
+ mpq_t ori,
+ unsigned const max_den);
+
+/* ========================================================================= */
+/** @brief Overestimate the given coefficient by another rational that is
+ * representble with denominators not bigger than max_den^2.
+ * @param ori original coefficient that we want to represent as a/b with b <=
+ * max_den^2.
+ * @param dest we return here the resulting number, note that we always
+ * insure that the returned value is bigger than the original value.
+ * @param max_den maximum allowed denominator in the new representation. */
+void EXutilOverEstimate (mpq_t dest,
+ mpq_t ori,
+ unsigned const max_den);
+
+/* ========================================================================= */
+/** @brief Given an inequality, we try to re-write so that no denominator is
+ * bigger than the square of the given number, and ensuring validity. for
+ * coefficients that can't be `nacified' we leave them intact. the process
+ * imply adding multiples of the bounds on variables, and at the end, nicify
+ * the rhs of the inequality.
+ * @param max_den the square of this value is the maximum denominator allowed.
+ * @param a hand side of the inequality.
+ * @param sense sense of the inequality, it should be either 'L' or 'G'.
+ * @param b right hand side of the inequality.
+ * @param act_prob LP from where we draw the bounds on the variables.
+ * @param var_stat status (as defined in #EXmipinfo_t::var_stat) for all
+ * variables in the LP, in the internal QSopt ordering.
+ * @note The length of the a vector is at least nstruct, and we assume that
+ * entry a[k] corresnpond to the coefficient associated with the k-th
+ * structural variable inside. */
+void EXutilNicefy (mpq_QSdata * const act_prob,
+ const unsigned char *const var_stat,
+ const unsigned max_den,
+ mpq_t * a,
+ mpq_t b,
+ int const sense);
+
+/* ========================================================================= */
+/** @brief given a variable in internal number, return a pointer to its name.
+ * @param iid internal ordering number.
+ * @param QSlp pointer to the mpq_QSdata structure containing the LP.
+ * @param QSinv_map pointer to an array containing the inverse map from internal
+ * numbering to external numbering as in #EXmipinfo_t::inv_map.
+ * @return pointer to its name.
+ * @note If the variable is a slack variable, it return the name of the
+ * inequality. */
+#define EXutilIidToStr(iid,QSlp,QSinv_map) ({\
+ mpq_QSdata*const __EXlp = (QSlp);\
+ const int __EXeid = (QSinv_map)[(iid)];\
+ (__EXeid >= __EXlp->qslp->nstruct) ? __EXlp->qslp->rownames[__EXeid - __EXlp->qslp->nstruct] : __EXlp->qslp->colnames[__EXeid];})
+
+/* ========================================================================= */
+/** @brief Initialize the static variables at start-up */
+extern void EXutilDoInit (void);
+/* ========================================================================= */
+/** @brief Clear all memory related to the static variables */
+extern void EXutilDoClear (void);
+/* ========================================================================= */
+/** @} */
+/* end eg_exutil.h */
+#endif
diff --git a/qsopt_ex/eg_io.c b/qsopt_ex/eg_io.c
new file mode 100644
index 0000000..8dc53cd
--- /dev/null
+++ b/qsopt_ex/eg_io.c
@@ -0,0 +1,695 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ *
+ * 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
+ * */
+/** @file
+ * @ingroup EGio */
+/** @addtogroup EGio */
+/** @{ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+
+#ifdef HAVE_LIBBZ2
+# include <bzlib.h>
+#endif
+
+#ifdef HAVE_LIBZ
+# include <zlib.h>
+#endif
+
+#include "logging-private.h"
+
+#include "eg_io.h"
+
+/* file-types: */
+#define EGIO_PLAIN 0
+#define EGIO_ZLIB 1
+#define EGIO_BZLIB 2
+
+/* ========================================================================= */
+/** @brief Given a string 'input' this function uses EGioParse to separate
+ * up to N words in it, we assume that argc is an array of pointers to strings
+ * of size N, and note that the input array will be changed. */
+void EGioNParse (char *input,
+ int max_argc,
+ const char *delim,
+ const char *comment,
+ int *argc,
+ char **argv)
+{
+ const size_t clen = strlen(comment);
+ const size_t dlen = strlen(delim);
+ char __EGiobuff[256] =
+ "20000000000000000000000000000000" /* 000-031 */
+ "11111111111111111111111111111111" /* 032-063 */
+ "11111111111111111111111111111111" /* 064-095 */
+ "11111111111111111111111111111110" /* 096-127 */
+ "00000000000000000000000000000000" /* 128-159 */
+ "00000000000000000000000000000000" /* 160-191 */
+ "00000000000000000000000000000000" /* 192-223 */
+ "00000000000000000000000000000000";/* 224-255 */
+ int i, EGiostat = 0, cc;
+ char *cur;
+ /* set convertion table */
+ for( i = clen ; i-- ; )
+ {
+ cc = comment[i];
+ if(cc>31 && cc<127) __EGiobuff[cc] = '2';
+ }
+ for( i = dlen ; i-- ; )
+ {
+ cc = delim[i];
+ if(cc>31 && cc<127) __EGiobuff[cc] = '0';
+ }
+ /* now parse */
+ *argc = EGiostat = 0;
+ cur = input;
+ while(cur && (*argc) < max_argc)
+ {
+ cc = __EGiobuff[(int)(*cur)];
+ switch(cc)
+ {
+ case '1':
+ if(!EGiostat) argv[(*argc)++] = cur;
+ EGiostat = 1;
+ cur++;
+ break;
+ case '0':
+ EGiostat = 0;
+ *(cur++) = '\0';
+ break;
+ case '2':
+ *cur = '\0';
+ cur = 0;
+ break;
+ default:
+ EXIT(1,"Imposible, cc=%c, cur = %c, pos %zd",cc, *cur, cur-input);
+ }
+ }
+ /* cleanup */
+ for( i = clen ; i-- ; )
+ {
+ cc = comment[i];
+ if(cc>31 && cc<127) __EGiobuff[cc] = '1';
+ }
+ for( i = dlen ; i-- ; )
+ {
+ cc = delim[i];
+ if(cc>31 && cc<127) __EGiobuff[cc] = '1';
+ }
+ return;
+}
+
+/* given two *pointers 'next' and 'current' and a constant set
+ * of strings (parse delimiters), it store in 'next the next
+ * meaningfull string, and in current the rest of the secuence,
+ * the idea is to iterate over 'next' while it is not true;
+ * you have to store the original pointer to the string stream
+ * elsewere; also, we assume that the original stream is
+ * terminated with '\0'; also, it will discaard any sub-string
+ * that start with #, that is inteded for discard comments.
+ * NOTE: this function WILL change the original string!!!!!
+ * There is no guarantee on how it will be changed. */
+void EGioParse (char **next,
+ char **current,
+ const char *delim,
+ const char *comment)
+{
+ /* local variables */
+ const size_t clen = strlen(comment);
+ const size_t dlen = strlen(delim);
+ char __EGiobuff[256] =
+ "20000000000000000000000000000000" /* 000-031 */
+ "11111111111111111111111111111111" /* 032-063 */
+ "11111111111111111111111111111111" /* 064-095 */
+ "11111111111111111111111111111110" /* 096-127 */
+ "00000000000000000000000000000000" /* 128-159 */
+ "00000000000000000000000000000000" /* 160-191 */
+ "00000000000000000000000000000000" /* 192-223 */
+ "00000000000000000000000000000000";/* 224-255 */
+ int i, EGiostat = 0, cc;
+ char *cur;
+ /* set convertion table */
+ for( i = clen ; i-- ; )
+ {
+ cc = comment[i];
+ if(cc>31 && cc<127) __EGiobuff[cc] = '2';
+ }
+ for( i = dlen ; i-- ; )
+ {
+ cc = delim[i];
+ if(cc>31 && cc<127) __EGiobuff[cc] = '0';
+ }
+ /* parse */
+ *next = 0;
+ cur = *current;
+ while(cur)
+ {
+ cc = __EGiobuff[(int)(*cur)];
+ switch(cc)
+ {
+ case '1':
+ if(!EGiostat) *next = cur;
+ EGiostat = 1;
+ cur++;
+ break;
+ case '0':
+ *(cur++) = '\0';
+ if(EGiostat)
+ {
+ *current = cur;
+ cur = 0;
+ }
+ EGiostat = 0;
+ break;
+ case '2':
+ *cur = '\0';
+ *current = cur = 0;
+ break;
+ default:
+ EXIT(1,"Imposible, cc=%c, cur = %c, pos %zd",cc, *cur, cur-*current);
+ }
+ }
+ /* cleanup */
+ for( i = clen ; i-- ; )
+ {
+ cc = comment[i];
+ if(cc>31 && cc<127) __EGiobuff[cc] = '1';
+ }
+ for( i = dlen ; i-- ; )
+ {
+ cc = delim[i];
+ if(cc>31 && cc<127) __EGiobuff[cc] = '1';
+ }
+ return;
+}
+
+/* this discard all lines starting with comments and stores the next
+ * leading line in current and the next token in next, we assume that next
+ * does not contain data, and that current store the remainings of the
+ * current line */
+void EGioDisCom (char **next,
+ char **current,
+ const char *delim,
+ const char *comment,
+ char *store,
+ unsigned int storeSize,
+ FILE * in)
+{
+ /* local variables */
+ int status = 1;
+
+ /* if no current line we read it from the file */
+ if (!(*current))
+ {
+ status = (store == fgets (store, (int) storeSize, in));
+ *current = store;
+ }
+ /* we process the current line, and while the line does
+ * not have a token we look the next line */
+ EGioParse (next, current, delim, comment);
+ while (!(*next) && status)
+ {
+ status = (store == fgets (store, (int) storeSize, in));
+ *current = store;
+ EGioParse (next, current, delim, comment);
+ }
+ /* ending */
+ return;
+}
+
+/* ========================================================================= */
+void EGdisplayString (void *str,
+ FILE * file)
+{
+ fprintf (file, "%s", (char *) str);
+}
+
+/* ========================================================================= */
+int EGioReadLine(char*const str,size_t const max_len, FILE*file)
+{
+ char *rc = fgets(str,max_len,file);
+ int rval = !rc;
+ FTESTG(rval, CLEANUP,"Nothing to be read");
+ CLEANUP:
+ return rval;
+ /*
+ int c=0;
+ size_t len = max_len ;
+ while(((c=getc(file))!=EOF) && (c!='\n') && --len)
+ {
+ str[max_len-1-len] = (char)c;
+ }
+ str[max_len-len] = '\0';
+ FTEST((max_len - len)==0 && c!= '\n',"Nothing to be read");
+ return 0;
+ */
+}
+/* ========================================================================= */
+int EGioReadNamedDblPlusParam(const int argc,
+ char**argv,
+ const char*const name,
+ double*const param,
+ int*const has_param,
+ int*const rval)
+{
+ const size_t len = strlen(name)+5;
+ int fail=0;
+ *rval = 0;
+ if(argc<1) return 0;
+ if(strncmp(argv[0],name,len)==0)
+ {
+ FTESTG((fail=(argc!=2)),CLEANUP,"%s has not 2 tokens",name);
+ FTESTG((fail=(*has_param)),CLEANUP,"%s keyword repeated",name);
+ *param = strtod(argv[1],0);
+ FTESTG((fail=((*param)<0)),CLEANUP,"%s should be positive,"
+ "is %lf",name,*param);
+ *has_param = 1;
+ return 1;
+ }
+ else
+ return 0;
+ CLEANUP:
+ *rval=1;
+ return fail;
+}
+/* ========================================================================= */
+int EGioReadNamedIntPlusParam(const int argc,
+ char**argv,
+ const char*const name,
+ int*const param,
+ int*const has_param,
+ int*const rval)
+{
+ const size_t len = strlen(name)+5;
+ int fail=0;
+ *rval = 0;
+ if(argc<1) return 0;
+ if(strncmp(argv[0],name,len)==0)
+ {
+ FTESTG((fail=(argc!=2)),CLEANUP,"%s has not 2 tokens",name);
+ FTESTG((fail=(*has_param)),CLEANUP,"%s keyword repeated",name);
+ *param = atoi(argv[1]);
+ FTESTG((fail=((*param)<1)),CLEANUP,"%s should be positive,"
+ "is %d",name,*param);
+ *has_param = 1;
+ return 1;
+ }
+ else
+ return 0;
+ CLEANUP:
+ *rval=1;
+ return fail;
+}
+/* ========================================================================= */
+int EGioReadNamedIntNNParam(const int argc,
+ char**argv,
+ const char*const name,
+ int*const param,
+ int*const has_param,
+ int*const rval)
+{
+ const size_t len = strlen(name)+5;
+ int fail=0;
+ *rval = 0;
+ if(argc<1) return 0;
+ if(strncmp(argv[0],name,len)==0)
+ {
+ FTESTG((fail=(argc!=2)),CLEANUP,"%s has not 2 tokens",name);
+ FTESTG((fail=(*has_param)),CLEANUP,"%s keyword repeated",name);
+ *param = atoi(argv[1]);
+ FTESTG((fail=((*param)<0)),CLEANUP,"%s should be positive,"
+ "is %d",name,*param);
+ *has_param = 1;
+ return 1;
+ }
+ else
+ return 0;
+ CLEANUP:
+ *rval=1;
+ return fail;
+}
+/* ========================================================================= */
+int EGioReadNamedStringParam(const int argc,
+ char**argv,
+ const char*const name,
+ char**const param,
+ int*const has_param,
+ int*const rval)
+{
+ const size_t len = strlen(name)+5;
+ int fail=0;
+ *rval = 0;
+ if(argc<1) return 0;
+ if(strncmp(argv[0],name,len)==0)
+ {
+ FTESTG((fail=(argc!=2)),CLEANUP,"%s has not 2 tokens",name);
+ FTESTG((fail=(*has_param)),CLEANUP,"%s keyword repeated",name);
+ if(param) *param = strdup(argv[1]);
+ *has_param = 1;
+ return 1;
+ }
+ else
+ return 0;
+ CLEANUP:
+ *rval=1;
+ return fail;
+}
+/* ========================================================================= */
+int EGioReadNamedParam( const int argc,
+ char**argv,
+ const char*const name,
+ int*const has_param,
+ int*const rval)
+{
+ const size_t len = strlen(name)+5;
+ int fail=0;
+ *rval = 0;
+ if(argc<1) return 0;
+ if(strncmp(argv[0],name,len)==0)
+ {
+ FTESTG((fail=(argc!=1)),CLEANUP,"%s has not 1 token",name);
+ FTESTG((fail=(*has_param)),CLEANUP,"%s keyword repeated",name);
+ *has_param = 1;
+ return 1;
+ }
+ else
+ return 0;
+ CLEANUP:
+ *rval=1;
+ return fail;
+}
+/* ========================================================================= */
+
+int EGioReadIntParam( const int argc,
+ char**argv,
+ int*const param,
+ int*const rval)
+{
+ *rval = 0;
+ if(argc<1) return 0;
+ FTESTG((argc!=1),CLEANUP,"line has not 1 token");
+ *param = atoi(argv[0]);
+ return 0;
+ CLEANUP:
+ *rval=1;
+ return 1;
+}
+/* ========================================================================= */
+#define EGio_BUFSIZE 4096
+/* ========================================================================= */
+struct EGioFile_st {int type; void*file;};
+/* ========================================================================= */
+int EGioWrite(EGioFile_t*file,const char*const string)
+{
+ char buf[EGio_BUFSIZE];
+ int len;
+ buf[EGio_BUFSIZE-1] = 0;
+ snprintf(buf,EGio_BUFSIZE,"%s",string);
+ len = strlen(buf);
+ if(len<=0 || len >= EGio_BUFSIZE || buf[EGio_BUFSIZE-1]!=0) return 0;
+ switch(file->type)
+ {
+ case EGIO_PLAIN:
+ return fwrite(buf, (size_t)1, (size_t)len, (FILE*)(file->file));
+ case EGIO_ZLIB:
+#ifdef HAVE_LIBZ
+ return gzwrite((gzFile)(file->file),buf,(unsigned)len);
+#else
+ QSlog("no zlib support");
+ return 0;
+#endif
+ case EGIO_BZLIB:
+#ifdef HAVE_LIBBZ2
+ return BZ2_bzwrite((BZFILE*)(file->file),buf,len);
+#else
+ QSlog("no bzip2 support");
+ return 0;
+#endif
+ default:
+ QSlog("UNKNOWN FILE TYPE %d", file->type);
+ return 0;
+ }
+}
+/* ========================================================================= */
+int EGioPrintf(EGioFile_t*file,const char* format, ...)
+{
+ char buf[EGio_BUFSIZE];
+ va_list va;
+ buf[EGio_BUFSIZE-1]=0;
+ va_start(va,format);
+ vsnprintf(buf,EGio_BUFSIZE,format,va);
+ va_end(va);
+ return EGioWrite(file,buf);
+}
+/* ========================================================================= */
+EGioFile_t* EGioOpenFILE(FILE*ifile)
+{
+ EGioFile_t* file= (EGioFile_t*)malloc(sizeof(EGioFile_t));
+ if(!file) goto CLEANUP;
+ file->type = EGIO_PLAIN;
+ file->file = ifile;
+ if(!file->file)
+ {
+ free(file);
+ file = 0;
+ }
+ CLEANUP:
+ return file;
+}
+/* ========================================================================= */
+EGioFile_t* EGioOpen(const char *path, const char *mode)
+{
+ char lmode[8];
+ int len = strlen(path);
+ EGioFile_t* file= (EGioFile_t*)malloc(sizeof(EGioFile_t));
+ if(!file) goto CLEANUP;
+ if(len>3 && path[len-3] == '.' && path[len-2] == 'g' && path[len-1] == 'z')
+ {
+ file->type = EGIO_ZLIB;
+ if(index(mode,'b')) snprintf(lmode,7,"%s",mode);
+ else snprintf(lmode,7,"%s9b",mode);
+ }
+ else if(len>4 && path[len-4] == '.' && path[len-3] == 'b' && path[len-2] == 'z' && path[len-1] == '2')
+ {
+ file->type = EGIO_BZLIB;
+ if(index(mode,'b')) snprintf(lmode,7,"%s",mode);
+ else snprintf(lmode,7,"%sb",mode);
+ }
+ else
+ {
+ file->type = EGIO_PLAIN;
+ snprintf(lmode,7,"%s",mode);
+ }
+ switch(file->type)
+ {
+ case EGIO_PLAIN:
+ file->file = fopen(path,lmode);
+ break;
+ case EGIO_ZLIB:
+#ifdef HAVE_LIBZ
+ file->file = gzopen(path,lmode);
+#else
+ QSlog("no zlib support");
+ file->file = 0;
+#endif
+ break;
+ case EGIO_BZLIB:
+#ifdef HAVE_LIBBZ2
+ file->file = BZ2_bzopen(path,lmode);
+#else
+ QSlog("no bzip2 support");
+ file->file = 0;
+#endif
+ break;
+ default:
+ QSlog("UNKNOWN FILE TYPE %d",file->type);
+ file->file = 0;
+ break;
+ }
+ if(!file->file)
+ {
+ const int __EGserrno = errno;
+ free(file);
+ errno = __EGserrno;
+ return NULL;
+ }
+ CLEANUP:
+ return file;
+}
+/* ========================================================================= */
+int EGioClose(EGioFile_t*file)
+{
+ int rval = 0;
+ if(!file) return 0;
+ switch(file->type)
+ {
+ case EGIO_PLAIN:
+ if( (((FILE*)(file->file)) != stdin) &&
+ (((FILE*)(file->file)) != stdout) &&
+ (((FILE*)(file->file)) != stderr))
+ rval = fclose((FILE*)(file->file));
+ break;
+ case EGIO_ZLIB:
+#ifdef HAVE_LIBZ
+ rval = gzclose((gzFile)(file->file));
+#else
+ QSlog("no zlib support");
+ rval = EOF;
+#endif
+ break;
+ case EGIO_BZLIB:
+#ifdef HAVE_LIBBZ2
+ BZ2_bzerror((BZFILE*)(file->file),&rval);
+ BZ2_bzclose((BZFILE*)(file->file));
+#else
+ QSlog("no bzip2 support");
+ rval = EOF;
+#endif
+ break;
+ default:
+ QSlog("UNKNOWN FILE TYPE %d", file->type);
+ rval = EOF;
+ break;
+ }
+ free(file);
+ return rval;
+}
+/* ========================================================================= */
+int EGioFlush(EGioFile_t*file)
+{
+ switch(file->type)
+ {
+ case EGIO_PLAIN:
+ return fflush((FILE*)(file->file));
+ case EGIO_ZLIB:
+#ifdef HAVE_LIBZ
+ /*return gzflush((gzFile)(file->file),Z_FINISH);*/
+ return 0;
+#else
+ QSlog("no zlib support");
+ return EOF;
+#endif
+ case EGIO_BZLIB:
+#ifdef HAVE_LIBBZ2
+ return 0;
+#else
+ QSlog("no bzip2 support");
+ return EOF;
+#endif
+ default:
+ QSlog("UNKNOWN FILE TYPE %d", file->type);
+ return EOF;
+ }
+}
+/* ========================================================================= */
+char* EGioGets(char*buf, int len, EGioFile_t*file)
+{
+ char*b = buf;
+ switch(file->type)
+ {
+ case EGIO_PLAIN:
+ return fgets(buf,len,(FILE*)(file->file));
+ case EGIO_ZLIB:
+#ifdef HAVE_LIBZ
+ return gzgets((gzFile)(file->file),buf,len);
+#else
+ QSlog("no zlib support");
+ return NULL;
+#endif
+ case EGIO_BZLIB:
+#ifdef HAVE_LIBBZ2
+ if(buf == 0 || len <=0 ) return NULL;
+ while( --len > 0 && BZ2_bzread(((BZFILE*)(file->file)), buf, 1) == 1 && *buf++ != '\n') ;
+ *buf = '\0';
+ return b == buf && len >0 ? NULL : b ;
+#else
+ QSlog("no bzip2 support");
+ return NULL;
+#endif
+ default:
+ QSlog("UNKNOWN FILE TYPE %d", file->type);
+ return NULL;
+ }
+}
+/* ========================================================================= */
+int EGioEof(const EGioFile_t*const file)
+{
+ int err;
+ switch(file->type)
+ {
+ case EGIO_PLAIN:
+ return feof((FILE*)(file->file));
+ case EGIO_ZLIB:
+#ifdef HAVE_LIBZ
+ return gzeof((gzFile)(file->file));
+#else
+ QSlog("no zlib support");
+ return 1;
+#endif
+ case EGIO_BZLIB:
+#ifdef HAVE_LIBBZ2
+ BZ2_bzerror(((BZFILE*)(file->file)),&err);
+ return err == BZ_STREAM_END;
+#else
+ QSlog("no bzip2 support");
+ return 1;
+#endif
+ default:
+ QSlog("UNKNOWN FILE TYPE %d", file->type);
+ return 1;
+ }
+}
+/* ========================================================================= */
+int EGioError(const EGioFile_t*const file)
+{
+ int errnum;
+ switch(file->type)
+ {
+ case EGIO_PLAIN:
+ return ferror((FILE*)(file->file));
+ case EGIO_ZLIB:
+#ifdef HAVE_LIBZ
+ gzerror((gzFile)(file->file),&errnum);
+ return errnum;
+#else
+ QSlog("no zlib support");
+ return 1;
+#endif
+ case EGIO_BZLIB:
+#ifdef HAVE_LIBBZ2
+ BZ2_bzerror(((BZFILE*)(file->file)),&errnum);
+ return errnum;
+#else
+ QSlog("no bzip2 support");
+ return 1;
+#endif
+ default:
+ QSlog("UNKNOWN FILE TYPE %d", file->type);
+ return 1;
+ }
+}/* ========================================================================= */
+/** @} */
diff --git a/qsopt_ex/eg_io.h b/qsopt_ex/eg_io.h
new file mode 100644
index 0000000..8680606
--- /dev/null
+++ b/qsopt_ex/eg_io.h
@@ -0,0 +1,338 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ *
+ * 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
+ * */
+
+/* ========================================================================= */
+/** @defgroup EGio EGio
+ * input/output utilities
+ *
+ * Version 0.0.2 2003-05-09 (Marcos)
+ *
+ * Added the function EGioNParse to get a more argc, argv feel.
+ * Also: Changed EGioParse so that it ignores multiple sequential delimiters.
+ *
+ * Version 0.0.1 2003-04-11
+ * - 2004-08-17
+ * - Add EGdisplayString function.
+ * - 2006-08-16
+ * - Add EGioReadLine function.
+ * - 2007-12-06
+ * - Add EGioReadxxxParam functions
+ * - 2009-10-19
+ * - Add bzlib/zlib/plain text interface
+ * */
+/** @file
+ * @ingroup EGio */
+/** @addtogroup EGio */
+/** @{
+ * @example eg_ebtree.ex.c
+ * This is an example of writing to a zlib-compresed file
+ *
+ * @example eg_min_cut.ex.c
+ * This is an example of reading files, either plain, bz2 or gz
+ * */
+/* ========================================================================= */
+
+#ifndef __EG_IO_H__
+#define __EG_IO_H__
+
+#include "eg_macros.h"
+
+/* ========================================================================= */
+/** @brief safe open function, it test that we can open the given file with the
+ * given mode, if an error occurs, display it on screen and exit, otherwise,
+ * return the open file stream.
+ * @param __file file name to open (is a const char*)
+ * @param __mode mode to use to open the file (is a const char*)
+ * @return FILE* stream */
+#define EGsfopen(__file,__mode) ({\
+ const char*__EGsfile = (__file);\
+ const char*__EGsmode = (__mode);\
+ FILE*__EGsFILE = fopen(__EGsfile,__EGsmode);\
+ if(!__EGsFILE)\
+ {\
+ const int __EGserrno = errno;\
+ fprintf(stderr,"fopen() failed with error code %d, error\n%s",__EGserrno,strerror(__EGserrno));\
+ MESSAGE(0,"Could not open %s with mode %s", __EGsfile, __EGsmode);\
+ exit(__EGserrno);\
+ }\
+ __EGsFILE;})
+
+/* ========================================================================= */
+/**@brief type of functions for display, receives a void* to the structure to print,
+ * and a *FILE where to output */
+typedef void (*EGdisplay_f) (void *, FILE *);
+#define EGnullDisplay ((EGdisplay_f)0)
+
+/* ========================================================================= */
+/** @brief type of functions for display, receives a void* to the structure to print, a
+ * *FILE where to output, and a set of offsets for datas, the length of that
+ * array must be know by the user. */
+typedef void (*EGdisplayOS_f) (void *,
+ FILE *,
+ size_t *);
+
+/* ========================================================================= */
+/** @brief Given a string 'input' this function uses EGioParse to separate
+ * up to N words in it, we assume that argc is an array of pointers to strings
+ * of size N, and note that the input array will be changed. */
+void EGioNParse (char *input,
+ int max_argc,
+ const char *delim,
+ const char *comment,
+ int *argc,
+ char **argv);
+
+/* ========================================================================= */
+/** @brief given two *pointers 'next' and 'current' and a constant set
+ * of strings (parse delimiters), it store in 'next the next
+ * meaningfull string, and in current the rest of the secuence,
+ * the idea is to iterate over 'next' while it is not true;
+ * you have to store the original pointer to the string stream
+ * elsewere; also, we assume that the original stream is
+ * terminated with '\0'; also, it will discaard any sub-string
+ * that start with #, that is inteded for discard comments */
+void EGioParse (char **next,
+ char **current,
+ const char *delim,
+ const char *coment);
+
+/* ========================================================================= */
+/** @brief read a line from an input stream.
+ * @param str where to store the line.
+ * @param max_len maximum allowed length.
+ * @param file stream from where we read the input
+ * @return zero on success, non-zero otherwise, errors are cast when we can not
+ * read from the given file.
+ * */
+int EGioReadLine(char*const str,size_t const max_len, FILE*file);
+
+/* ========================================================================= */
+/** @brief read a named string parameter, this function checks that we have two
+ * parameters, and check if we had previously readed the parameter, if an error
+ * occurs, report it in the given rval
+ * @param argc number of tokens in the current line
+ * @param argv array of strings of tokens
+ * @param name named of the parameter
+ * @param param where to save the parameter (if null, don't save it)
+ * @param has_param if we had the parameter before, should be one, if not,
+ * should be zero, if successfull, then it will be set to one.
+ * @param rval return value if an error while reading occurs.
+ * @return one if we found the parameter in the line, or if we had an error
+ * while reading the named parameter, zero otherwise. */
+int EGioReadNamedStringParam( const int argc,
+ char**argv,
+ const char*const name,
+ char**const param,
+ int*const has_param,
+ int*const rval);
+/* ========================================================================= */
+/** @brief read a named, non-negative, integer parameter, this function checks that we have two
+ * parameters, and check if we had previously readed the parameter, if an error
+ * occurs, report it in the given rval
+ * @param argc number of tokens in the current line
+ * @param argv array of strings of tokens
+ * @param name named of the parameter
+ * @param param where to save the parameter (if null, don't save it)
+ * @param has_param if we had the parameter before, should be one, if not,
+ * should be zero, if successfull, then it will be set to one.
+ * @param rval return value if an error while reading occurs.
+ * @return one if we found the parameter in the line, or if we had an error
+ * while reading the named parameter, zero otherwise. */
+int EGioReadNamedIntNNParam(const int argc,
+ char**argv,
+ const char*const name,
+ int*const param,
+ int*const has_param,
+ int*const rval);
+/* ========================================================================= */
+/** @brief read a named, strictly positive, integer parameter, this function checks that we have two
+ * parameters, and check if we had previously readed the parameter, if an error
+ * occurs, report it in the given rval
+ * @param argc number of tokens in the current line
+ * @param argv array of strings of tokens
+ * @param name named of the parameter
+ * @param param where to save the parameter (if null, don't save it)
+ * @param has_param if we had the parameter before, should be one, if not,
+ * should be zero, if successfull, then it will be set to one.
+ * @param rval return value if an error while reading occurs.
+ * @return one if we found the parameter in the line, or if we had an error
+ * while reading the named parameter, zero otherwise. */
+int EGioReadNamedIntPlusParam(const int argc,
+ char**argv,
+ const char*const name,
+ int*const param,
+ int*const has_param,
+ int*const rval);
+/* ========================================================================= */
+/** @brief read a named positive double parameter, this function checks that we have two
+ * parameters, and check if we had previously readed the parameter, if an error
+ * occurs, report it in the given rval
+ * @param argc number of tokens in the current line
+ * @param argv array of strings of tokens
+ * @param name named of the parameter
+ * @param param where to save the parameter (if null, don't save it)
+ * @param has_param if we had the parameter before, should be one, if not,
+ * should be zero, if successfull, then it will be set to one.
+ * @param rval return value if an error while reading occurs.
+ * @return one if we found the parameter in the line, or if we had an error
+ * while reading the named parameter, zero otherwise. */
+int EGioReadNamedDblPlusParam(const int argc,
+ char**argv,
+ const char*const name,
+ double*const param,
+ int*const has_param,
+ int*const rval);
+/* ========================================================================= */
+/** @brief read a named parameter, this function checks that we have one
+ * parameter, and check if we had previously readed the parameter, if an error
+ * occurs, report it in the given rval
+ * @param argc number of tokens in the current line
+ * @param argv array of strings of tokens
+ * @param name named of the parameter
+ * @param has_param if we had the parameter before, should be one, if not,
+ * should be zero, if successfull, then it will be set to one.
+ * @param rval return value if an error while reading occurs.
+ * @return one if we found the parameter in the line, or if we had an error
+ * while reading the named parameter, zero otherwise. */
+int EGioReadNamedParam( const int argc,
+ char**argv,
+ const char*const name,
+ int*const has_param,
+ int*const rval);
+/* ========================================================================= */
+/** @brief read an integer parameter, this function checks that we have one
+ * parameter, if an error
+ * occurs, report it in the given rval
+ * @param argc number of tokens in the current line
+ * @param argv array of strings of tokens
+ * @param param named of the parameter
+ * should be zero, if successfull, then it will be set to one.
+ * @param rval return value if an error while reading occurs.
+ * @return one if we found the parameter in the line, or if we had an error
+ * while reading the named parameter, zero otherwise. */
+int EGioReadIntParam( const int argc,
+ char**argv,
+ int*const param,
+ int*const rval);
+
+/* ========================================================================= */
+/** @name Zlib, BZlib compability interface:
+ * This functions pretend to provide a common interface to work with plain or
+ * compresed files. Up to now, we implement zlib and plain text handling, as
+ * well as basic input/output handling. */
+/* @{ */
+/* ========================================================================= */
+/* ========================================================================= */
+struct EGioFile_st;
+typedef struct EGioFile_st EGioFile_t;
+/* ========================================================================= */
+/* comon functions */
+/* ========================================================================= */
+/** @brief Converts, formats, and writes the args to the file under control
+ * of the format string, as in fprintf.
+ * @return the number of bytes actually written (0 in case of error).
+ * @note The number of bytes written is limited to 4095 (inherited from
+ * gzprintf). The caller should assure that this limit is not exceeded.
+ * If it is exceeded, then EGioprintf() will return 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. For more details,
+ * see zlib's manual. */
+int EGioPrintf(EGioFile_t*file,const char *format, ...);
+int EGioWrite(EGioFile_t*file,const char* buf);
+/* ========================================================================= */
+/** @brief open a file for read or write as in fopen. if the file name ends
+ * with gz, it will (try to) use gzFile mode, if not, it will use regular FILE
+ * modes
+ * @return on success, pointer to an EGioFile_t structure, if can not open
+ * file, it will print system error on screen and exit execution. */
+EGioFile_t* EGioOpen(const char *path, const char *mode);
+/* ========================================================================= */
+/** @brief open a C stdandard file FILE as an EGioFile_t, it can be used to
+ * open stderr, stdout, stdin, it will use plain access to the file. At
+ * closing, it will not close the three standard stdout, stderr, stdin, but
+ * other files will be closed.
+ * @param file pointer to a std-c FILE structure
+ * @return pointer to a EGioFile_t structure, linked to the given file.
+ * @note we assume that file points to an already opened file.
+ * */
+EGioFile_t* EGioOpenFILE(FILE*file);
+/* ========================================================================= */
+/** @brief close file, flush all pending information, free all internally
+ * allocated information.
+ * @return zero on success; non-zero otherwise
+ * */
+int EGioClose(EGioFile_t*file);
+/* ========================================================================= */
+/** @brief flush all un-writed information into the file.
+ * @return zero on success, non-zero otherwise. */
+int EGioFlush(EGioFile_t*file);
+/* ========================================================================= */
+/** @brief reads bytes from 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. The string is then terminated with a null character.
+ * @return buf on success, 0 otherwise.
+ * */
+char* EGioGets(char*buf, int len, EGioFile_t*file);
+/* ========================================================================= */
+/** @brief Test if the given file stream pointer point to the end of file.
+ * @return non-zero if stream pointer points to end of file, 0 otherwise.
+ * */
+int EGioEof(const EGioFile_t*const file);
+/* ========================================================================= */
+/** @brief Test if the given file stream has an internal error flag
+ * @return zero if no error detected, otherwise, return the apropiate error
+ * code */
+int EGioError(const EGioFile_t*const file);
+/* ========================================================================= */
+/* end interface for zlib-compresed files */
+/* @} */
+/* ========================================================================= */
+/** @name Deprecated Functions
+ * All functions here are marked as deprecated, and may be discontinued in
+ * sub-sequent releases */
+/* @{ */
+/* ========================================================================= */
+/** @brief this discard all lines starting with comments and stores the next
+ * leading line in current and the next token in next, we assume that next
+ * does not contain data, and that current store the remainings of the
+ * current line */
+void EGioDisCom (char **next,
+ char **current,
+ const char *delim,
+ const char *coment,
+ char *store,
+ unsigned int storeSize,
+ FILE * in);
+/* ========================================================================= */
+/** @brief display function for strings
+ * @param str pointer to a null terminated string of chars.
+ * @param file pointer to a stream where we write the string.
+ * @par Description:
+ * This function just print the string on the file, it won't add a '\n' at the
+ * end. */
+void EGdisplayString (void *str,
+ FILE * file);
+
+/* @} */
+/* ========================================================================= */
+/** @} */
+#endif
diff --git a/qsopt_ex/eg_lpnum.c b/qsopt_ex/eg_lpnum.c
new file mode 100644
index 0000000..bd957cd
--- /dev/null
+++ b/qsopt_ex/eg_lpnum.c
@@ -0,0 +1,905 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ *
+ * 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
+ * */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <stdint.h>
+
+#include <gmp.h>
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "eg_memslab.h"
+#include "eg_nummacros.h"
+
+/** @file
+ * @ingroup EGlpNum */
+/** @addtogroup EGlpNum */
+/** @{ */
+/* ========================================================================= */
+/** @brief This constant define the acuracy required while
+ * converting doubles to rationals, a good number is 1e-5. More exactly, we
+ * stop the continued fraction method whenever the next e_i-[e_i] computed is
+ * less than EGLPNUM_MINEPS. Note that this value can't be smaller than
+ * 1/ULONG_MAX, otherwise we will have problems in the confertion step. */
+#ifndef EGLPNUM_MINEPS
+#define EGLPNUM_MINEPS 0x1ep-20
+#else
+#if EGLPNUM_MINEPS < 3e-10
+#undef EGLPNUM_MINEPS
+#define EGLPNUM_MINEPS 3e-10
+#endif
+#endif
+
+
+/* ========================================================================= */
+/** @brief if non-zero, use slab-pool allocator for GMP, otherwise, use malloc/
+ * realloc / free, */
+#ifndef EG_LPNUM_MEMSLAB
+#define EG_LPNUM_MEMSLAB 1
+#endif
+/* ========================================================================= */
+/** @brief type-dependant constants and helper numbers @{ */
+mpz_t __zeroLpNum_mpz__;
+mpz_t __oneLpNum_mpz__;
+mpz_t __MaxLpNum_mpz__;
+mpz_t __MinLpNum_mpz__;
+mpq_t __zeroLpNum_mpq__;
+mpq_t __oneLpNum_mpq__;
+mpq_t __MaxLpNum_mpq__;
+mpq_t __MinLpNum_mpq__;
+mpf_t __zeroLpNum_mpf__;
+mpf_t __MaxLpNum_mpf__;
+mpf_t __MinLpNum_mpf__;
+mpf_t __oneLpNum_mpf__;
+mpf_t mpf_eps;
+unsigned long int EGLPNUM_PRECISION = 128;
+
+/** @} */
+
+/* ========================================================================= */
+static int __EGlpNum_setup=0;
+/* ========================================================================= */
+/** @name data to handle memory allocations within gmp */
+/** @{*/
+#define __GMP_MEM_VERBOSE 100
+#define __GMP_MEM_STATS__ 0
+#define __GMP_MEM_MAX__ 256
+static const uint8_t _EGgmpPlTable[257] = \
+ { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* pool for 0-16 bytes */
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* pool for 17-32 bytes */
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, /* pool for 33-64 bytes */
+ 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
+ 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3, /* pool for 65-128 bytes */
+ 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+ 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+ 3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, /* pool for 129-255 bytes */
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
+ 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4};
+static const size_t _EGgmpPlSz[5] = {16,32,64,128,256};
+#define __GMP_MEM_NPOOL__ 5
+EGmemSlabPool_t EGgmpPl[__GMP_MEM_NPOOL__];
+#if __GMP_MEM_STATS__
+static size_t __alloc_sz[__GMP_MEM_NPOOL__] = {0,0,0,0,0};
+static size_t __rlloc_sz[__GMP_MEM_NPOOL__] = {0,0,0,0,0};
+static size_t __totmem = 0;
+static size_t __maxmem = 0;
+static size_t __nallocs = 0;
+static size_t __nrllocs = 0;
+static size_t __nalarge = 0;
+static size_t __nrlarge = 0;
+static size_t __laaverage=0;
+static size_t __lraverage=0;
+#endif
+/** @}*/
+/* ========================================================================= */
+#if __GMP_MEM_STATS__
+#define _TACC(__m) do{\
+ __totmem += __m;\
+ if(__totmem > __maxmem) __maxmem = __totmem;}while(0)
+#else
+#define _TACC(__m)
+#endif
+/* ========================================================================= */
+#if __GMP_MEM_STATS__
+#define _AACC(__a) do{\
+ __nallocs++;\
+ if((__a) <= __GMP_MEM_MAX__)\
+ __alloc_sz[_EGgmpPlTable[__a]]++;\
+ else{\
+ __nalarge++;\
+ __laaverage += (__a);}}while(0)
+#else
+#define _AACC(__a)
+#endif
+/* ========================================================================= */
+/** @brief dummy malloc function for gmp, at this stage is used for
+ * creating an account of the allocation */
+static void* __EGgmp_malloc(size_t sz)
+{
+ void*ptr = 0;
+ _TACC(sz);
+ _AACC(sz);
+ if(sz <= __GMP_MEM_MAX__)
+ {
+ ptr = EGmemSlabPoolAlloc(EGgmpPl+_EGgmpPlTable[sz]);
+ MESSAGE(__GMP_MEM_VERBOSE,"alloc %p [%zd]",ptr, sz);
+ return ptr;
+ /*memset(ptr,0,sz);*/
+ }
+ else
+ {
+ ptr = malloc(sz);
+ if(!ptr) EXIT(1,"No more memory");
+ MESSAGE(__GMP_MEM_VERBOSE,"alloc %p [%zd]",ptr, sz);
+ return ptr;
+ }
+ /*QSlog("allocating %p [%zd]",ptr,sz);*/
+ /*return ptr;*/
+}
+/* ========================================================================= */
+#if __GMP_MEM_STATS__
+#define _RACC(__a) do{\
+ __nrllocs++;\
+ if(__a<__GMP_MEM_MAX__)\
+ __rlloc_sz[_EGgmpPlTable[__a]]++;\
+ else{\
+ __nrlarge++;\
+ __lraverage += (__a);}}while(0)
+#else
+#define _RACC(__a)
+#endif
+/* ========================================================================= */
+/** @brief dummy realloc for gmp */
+static void* __EGgmp_realloc(void*ptr,size_t osz,size_t nsz)
+{
+ const size_t a1 = nsz > __GMP_MEM_MAX__ ? __GMP_MEM_NPOOL__ : _EGgmpPlTable[nsz];
+ const size_t a2 = osz > __GMP_MEM_MAX__ ? __GMP_MEM_NPOOL__ : _EGgmpPlTable[osz];
+ const size_t msz = nsz > osz ? osz : nsz;
+ void*rptr=0;
+ #if __GMP_MEM_STATS__
+ _RACC(nsz);
+ __totmem -= osz;
+ _TACC(nsz);
+ #endif
+ if(a1 < __GMP_MEM_NPOOL__)
+ {
+ if(a2 == a1)
+ {
+ rptr = ptr;
+ MESSAGE(__GMP_MEM_VERBOSE,"realloc %p [%zd] to %p [%zd]",ptr, osz, rptr, nsz);
+ return rptr;
+ }
+ else
+ {
+ rptr = EGmemSlabPoolAlloc(EGgmpPl+a1);
+ memcpy(rptr,ptr,msz);
+ if(a2 < __GMP_MEM_NPOOL__)
+ {
+ MESSAGE(__GMP_MEM_VERBOSE,"realloc %p [%zd] to %p [%zd]",ptr, osz, rptr, nsz);
+ EGmemSlabPoolFree(ptr);
+ return rptr;
+ }
+ else
+ {
+ MESSAGE(__GMP_MEM_VERBOSE,"realloc %p [%zd] to %p [%zd]",ptr, osz, rptr, nsz);
+ EGfree(ptr);
+ return rptr;
+ }
+ }
+ }
+ else if(a2 < __GMP_MEM_NPOOL__)
+ {
+ rptr = EGmalloc(nsz);
+ memcpy(rptr,ptr,msz);
+ MESSAGE(__GMP_MEM_VERBOSE,"realloc %p [%zd] to %p [%zd]",ptr, osz, rptr, nsz);
+ EGmemSlabPoolFree(ptr);
+ return rptr;
+ }
+ else
+ {
+ rptr = EGrealloc(ptr,nsz);
+ MESSAGE(__GMP_MEM_VERBOSE,"realloc %p [%zd] to %p [%zd]",ptr, osz, rptr, nsz);
+ return rptr;
+ }
+ /*QSlog("Re-allocating %p [%zd] to %p [%zd]",ptr,osz,rptr,nsz);*/
+ /*return rptr;*/
+}
+/* ========================================================================= */
+/** @brief dummy free for gmp */
+static void __EGgmp_free(void*ptr,size_t sz)
+{
+ const size_t a = sz > __GMP_MEM_MAX__ ? __GMP_MEM_NPOOL__ : _EGgmpPlTable[sz];
+ #if __GMP_MEM_STATS__
+ __totmem -= sz;
+ #endif
+ MESSAGE(__GMP_MEM_VERBOSE,"freeing %p",ptr);
+ if(a<__GMP_MEM_NPOOL__)
+ {
+ EGmemSlabPoolFree(ptr);
+ return;
+ }
+ else
+ {
+ EGfree(ptr);
+ return;
+ }
+}
+
+/* ========================================================================= */
+/*void EGlpNumStart(void) __attribute__ ((constructor));*/
+void EGlpNumStart(void)
+{
+ int rval=0;
+ register int i;
+ if(__EGlpNum_setup) return;
+ if(EG_LPNUM_MEMSLAB)
+ {
+ for( i = __GMP_MEM_NPOOL__ ; i-- ; )
+ {
+ EGmemSlabPoolInit(EGgmpPl+i,_EGgmpPlSz[i],0,0);
+ rval = EGmemSlabPoolSetParam(EGgmpPl+i,EG_MSLBP_FREEFREE,0);
+ EXIT(rval,"Unknown error");
+ }
+ mp_set_memory_functions(__EGgmp_malloc, __EGgmp_realloc, __EGgmp_free);
+ }
+
+ mpf_set_default_prec (EGLPNUM_PRECISION);
+ mpz_init (__zeroLpNum_mpz__);
+ mpz_init (__oneLpNum_mpz__);
+ mpz_init (__MaxLpNum_mpz__);
+ mpz_init (__MinLpNum_mpz__);
+ mpz_set_ui (__zeroLpNum_mpz__, (unsigned long int)0);
+ mpz_set_ui (__oneLpNum_mpz__, (unsigned long int)1);
+ mpq_init (__MaxLpNum_mpq__);
+ mpq_init (__MinLpNum_mpq__);
+ mpf_init (__MaxLpNum_mpf__);
+ mpf_init (__MinLpNum_mpf__);
+ mpf_init (__zeroLpNum_mpf__);
+ mpf_init (__oneLpNum_mpf__);
+ mpf_set_ui(__MaxLpNum_mpf__,1UL);
+ mpf_set_si(__MinLpNum_mpf__,-1L);
+ mpf_mul_2exp(__MaxLpNum_mpf__,__MaxLpNum_mpf__,4096);
+ /*mpf_mul_2exp(__MaxLpNum_mpf__,__MaxLpNum_mpf__,ULONG_MAX);*/
+ mpf_mul_2exp(__MinLpNum_mpf__,__MinLpNum_mpf__,4096);
+ /*mpf_mul_2exp(__MinLpNum_mpf__,__MinLpNum_mpf__,ULONG_MAX);*/
+ mpq_set_f(__MaxLpNum_mpq__,__MaxLpNum_mpf__);
+ mpq_set_f(__MinLpNum_mpq__,__MinLpNum_mpf__);
+ mpz_set_f(__MaxLpNum_mpz__,__MaxLpNum_mpf__);
+ mpz_set_f(__MinLpNum_mpz__,__MinLpNum_mpf__);
+ mpf_set_ui (__oneLpNum_mpf__, (unsigned long int)1);
+ mpf_set_ui (__zeroLpNum_mpf__, (unsigned long int)0);
+ mpf_init_set_ui (mpf_eps, (unsigned long int)1);
+ mpf_div_2exp (mpf_eps, mpf_eps, (unsigned long int)(EGLPNUM_PRECISION - 1));
+ mpq_init (__zeroLpNum_mpq__);
+ mpq_init (__oneLpNum_mpq__);
+ mpq_set_ui (__oneLpNum_mpq__, (unsigned long int)1, (unsigned long int)1);
+ mpq_set_ui (__zeroLpNum_mpq__, (unsigned long int)0, (unsigned long int)1);
+ __EGlpNum_setup=1;
+}
+
+/* ========================================================================= */
+void EGlpNumSetPrecision (const unsigned prec)
+{
+ EGLPNUM_PRECISION = prec;
+ mpf_set_default_prec (EGLPNUM_PRECISION);
+ mpf_clear (mpf_eps);
+ mpf_init_set_ui (mpf_eps, (unsigned long int)1);
+ mpf_div_2exp (mpf_eps, mpf_eps, (unsigned long int)(EGLPNUM_PRECISION - 1));
+}
+
+/* ========================================================================= */
+/*void EGlpNumExit(void) __attribute__ ((destructor));*/
+void EGlpNumClear(void)
+{
+ #if __GMP_MEM_STATS__
+ const char mc[5][3] = {"b ","Kb","Mb","Gb","Tb"};
+ #endif
+ int i;
+ if(!__EGlpNum_setup) return;
+ mpf_clear (__zeroLpNum_mpf__);
+ mpf_clear (__oneLpNum_mpf__);
+ mpf_clear (__MaxLpNum_mpf__);
+ mpf_clear (__MinLpNum_mpf__);
+ mpf_clear (mpf_eps);
+ mpq_clear (__zeroLpNum_mpq__);
+ mpq_clear (__oneLpNum_mpq__);
+ mpq_clear (__MinLpNum_mpq__);
+ mpq_clear (__MaxLpNum_mpq__);
+ mpz_clear (__zeroLpNum_mpz__);
+ mpz_clear (__oneLpNum_mpz__);
+ mpz_clear (__MaxLpNum_mpz__);
+ mpz_clear (__MinLpNum_mpz__);
+ if(EG_LPNUM_MEMSLAB)
+ {
+ mp_set_memory_functions(0, 0, 0);
+ for(i = __GMP_MEM_NPOOL__ ; i-- ; )
+ {
+ EGmemSlabPoolClear(EGgmpPl+i);
+ }
+ #if __GMP_MEM_STATS__
+ QSlog("GMP alloc statistics:");
+ for( i = 0 ; i < __GMP_MEM_NPOOL__ ; i++)
+ {
+ if(__maxmem > 1024*1024) __maxmem= (__maxmem+1023)/1024;
+ else break;
+ }
+ QSlog("\tmaximum memory allocated : %8.3lf %s",
+ ((double)__maxmem)/1024, mc[i+1]);
+ QSlog("\tmalloc calls : %11zd",__nallocs);
+ QSlog("\trealloc calls : %11zd",__nrllocs);
+ QSlog("\tsmall size allocs-reallocs:");
+ for( i = 0 ; i < __GMP_MEM_NPOOL__ ; i++)
+ {
+ if(__alloc_sz[i] || __rlloc_sz[i])
+ QSlog("\t%4d %11zd (%5.2lf%%) %11zd (%5.2lf%%)",
+ _EGgmpPlSz[i], __alloc_sz[i],
+ 100.0*((double)__alloc_sz[i])/(__nallocs+__nrllocs),
+ __rlloc_sz[i],
+ 100.0*((double)__rlloc_sz[i])/(__nrllocs+__nallocs));
+ }
+ if(__nalarge)
+ QSlog("\tlarge size allocs (cals/avg) : %11zd %11zd",
+ __nalarge,__laaverage/__nalarge);
+ if(__nrlarge)
+ QSlog("\tlarge size reallocs (cals/avg): %11zd %11zd",
+ __nrlarge,__lraverage/__nalarge);
+ #endif
+ QSlog("Disabling EG-GMP mempool");
+ }
+ __EGlpNum_setup=0;
+}
+
+/* ========================================================================= */
+void mpq_EGlpNumSet_mpf (mpq_t var,
+ mpf_t flt)
+{
+ /* local variables */
+ unsigned long int __lsgn = mpf_cmp_ui (flt, (unsigned long int)0) < 0 ? (unsigned long int)1 : (unsigned long int)0;
+ mpz_t __utmp,
+ __z[7],
+ max_den;
+ long int __lexp = 0;
+ int i;
+ unsigned long int uexp;
+ mpf_t __cvl,__lpnum__;
+ mpf_init(__lpnum__);
+ /* check if the given number is zero, if so, set to zero var and return */
+ if (mpf_cmp_ui (flt, (unsigned long int)0) == 0)
+ {
+ mpq_set_ui (var, (unsigned long int)0, (unsigned long int)1);
+ return;
+ }
+ /* if not, then we have some work to do */
+ /* now we initialize the internal numbers */
+ mpf_init (__cvl);
+ mpf_abs (__cvl, flt);
+ mpz_init_set_ui (__utmp, (unsigned long int)0);
+ for (i = 7; i--;)
+ mpz_init_set_ui (__z[i], (unsigned long int)0);
+ mpz_set_ui (__z[0], (unsigned long int)1);
+ mpz_set_ui (__z[4], (unsigned long int)1);
+ /* max_den is the maximum denominator that we want to see, this number should
+ * be sligtly larger than the square root of 2^EGLPNUM_PRECISION */
+ mpz_init_set_ui (max_den, (unsigned long int)1);
+ mpz_mul_2exp (max_den, max_den, EGLPNUM_PRECISION >> 1);
+ /* first we compute the exponent stored in the limbs */
+ /* now we compute the 2^n part needed to set this number between 0.5 and 1 */
+ mpf_get_d_2exp(&__lexp,__cvl);
+ if (__lexp < 0)
+ {
+ uexp = (unsigned long int)(-__lexp);
+ mpf_mul_2exp (__cvl, __cvl, (unsigned long int) uexp);
+ }
+ else
+ {
+ uexp = (unsigned long int)(__lexp);
+ mpf_div_2exp (__cvl, __cvl, (unsigned long int) uexp);
+ }
+ /* now we loop until the next t's is more than mpf_eps */
+ /* the formula is
+ * p_i = t_i*p_{i-1} + p_{i-2}, and
+ * q_i = t_i*q_{i-1} + q_{i-2}
+ * note that |x-p_i/q_i|<1/q_i^2
+ * for us t_i = __utmp, and the current number is either [0,1,2] in the __z
+ * array, we use those popsitions ciclicly, and use the four position as a
+ * temporary number, __z+4 is used to store q's, at the beginning i = 1. */
+ while (1)
+ {
+ if (mpf_cmp (__cvl, mpf_eps) < 0 || (mpz_cmp (__z[4], max_den) > 0))
+ {
+ mpz_set (mpq_denref (var), __z[4]);
+ mpz_set (mpq_numref (var), __z[1]);
+ break;
+ }
+ /* first run */
+ mpf_ui_div (__cvl, (unsigned long int)1, __cvl);
+ mpz_set_f (__utmp, __cvl);
+ mpf_set_z (__lpnum__, __utmp);
+ mpf_sub (__cvl, __cvl, __lpnum__);
+ mpz_set (__z[6], __utmp);
+ mpz_set (__z[2], __z[0]);
+ mpz_addmul (__z[2], __z[1], __z[6]);
+ mpz_set (__z[5], __z[3]);
+ mpz_addmul (__z[5], __z[4], __z[6]);
+ if (mpf_cmp (__cvl, mpf_eps) < 0 || (mpz_cmp (__z[5], max_den) > 0))
+ {
+ mpz_set (mpq_denref (var), __z[5]);
+ mpz_set (mpq_numref (var), __z[2]);
+ break;
+ }
+ /* second run */
+ mpf_ui_div (__cvl, (unsigned long int)1, __cvl);
+ mpz_set_f (__utmp, __cvl);
+ mpf_set_z (__lpnum__, __utmp);
+ mpf_sub (__cvl, __cvl, __lpnum__);
+ mpz_set (__z[6], __utmp);
+ mpz_set (__z[0], __z[1]);
+ mpz_addmul (__z[0], __z[2], __z[6]);
+ mpz_set (__z[3], __z[4]);
+ mpz_addmul (__z[3], __z[5], __z[6]);
+ if (mpf_cmp (__cvl, mpf_eps) < 0 || (mpz_cmp (__z[3], max_den) > 0))
+ {
+ mpz_set (mpq_denref (var), __z[3]);
+ mpz_set (mpq_numref (var), __z[0]);
+ break;
+ }
+ /* third run */
+ mpf_ui_div (__cvl, (unsigned long int)1, __cvl);
+ mpz_set_f (__utmp, __cvl);
+ mpf_set_z (__lpnum__, __utmp);
+ mpf_sub (__cvl, __cvl, __lpnum__);
+ mpz_set (__z[6], __utmp);
+ mpz_set (__z[1], __z[2]);
+ mpz_addmul (__z[1], __z[0], __z[6]);
+ mpz_set (__z[4], __z[5]);
+ mpz_addmul (__z[4], __z[3], __z[6]);
+ }
+
+ /* ending */
+ mpq_canonicalize (var);
+ if (__lsgn)
+ mpq_neg (var, var);
+ if (__lexp > 0)
+ mpq_mul_2exp (var, var, (unsigned long int) __lexp);
+ if (__lexp < 0)
+ mpq_div_2exp (var, var, (unsigned long int) (-__lexp));
+ for (i = 7; i--;)
+ mpz_clear (__z[i]);
+ mpf_clear (__cvl);
+ mpz_clear (max_den);
+ mpz_clear (__utmp);
+ mpf_clear(__lpnum__);
+ return;
+}
+/* ========================================================================= */
+/** @brief verbosity of continued fraction conversion method */
+#ifndef MPQ_VERBOSE_CNT_FRAC
+#define MPQ_VERBOSE_CNT_FRAC 1000
+#endif
+/* ========================================================================= */
+void mpq_EGlpNumSet (mpq_t var,
+ double const dbl)
+{
+ /* local variables */
+ double __dbl = dbl;
+ unsigned __lsgn = __dbl > 0.0 ? 0U: 1U;
+ unsigned long __utmp = 0;
+ int __lexp = 0;
+ double __cvl = __dbl = fabs (__dbl);
+ /* we use the first three numbers for p, and the last three numbers for q */
+ /* first check that the dbl is not zero */
+ if (__dbl < 1e-151)
+ {
+ mpq_set_ui (var, (unsigned long int)0, (unsigned long int)1);
+ __lsgn = 0;
+ }
+ else if (__dbl > 1e151)
+ mpq_set_d (var, __dbl);
+ else
+ {
+ /* now we initialize the integer numbers */
+ mpz_t __z[7];
+ for (__utmp = 7; __utmp--;)
+ mpz_init (__z[__utmp]);
+ mpz_set_ui (__z[0], (unsigned long int)1);
+ mpz_set_ui (__z[4], (unsigned long int)1);
+ /* now we compute the 2^n part needed to set this number between 0 and 1 */
+#define __HI_EXP(x,e,v,lv) {if( x >=v ){ e = e + lv; x /= v;}}
+ if (__cvl > 1)
+ {
+ __HI_EXP (__cvl, __lexp,
+ 115792089237316195423570985008687907853269984665640564039457584007913129639936.0,
+ 256);
+ __HI_EXP (__cvl, __lexp, 340282366920938463463374607431768211456.0, 128);
+ __HI_EXP (__cvl, __lexp, 18446744073709551616.0, 64);
+ __HI_EXP (__cvl, __lexp, 4294967296.0, 32);
+ __HI_EXP (__cvl, __lexp, 65536.0, 16);
+ __HI_EXP (__cvl, __lexp, 256.0, 8);
+ __HI_EXP (__cvl, __lexp, 16.0, 4);
+ __HI_EXP (__cvl, __lexp, 4.0, 2);
+ __HI_EXP (__cvl, __lexp, 2.0, 1);
+#undef __HI_EXP
+ }
+ else if (__cvl < 0.5)
+ {
+#define __LO_EXP(x,e,v,lv) {if( x < 1/v ) { e = e - lv; x *= v;}}
+ __LO_EXP (__cvl, __lexp,
+ 115792089237316195423570985008687907853269984665640564039457584007913129639936.0,
+ 256);
+ __LO_EXP (__cvl, __lexp, 340282366920938463463374607431768211456.0, 128);
+ __LO_EXP (__cvl, __lexp, 18446744073709551616.0, 64);
+ __LO_EXP (__cvl, __lexp, 4294967296.0, 32);
+ __LO_EXP (__cvl, __lexp, 65536.0, 16);
+ __LO_EXP (__cvl, __lexp, 256.0, 8);
+ __LO_EXP (__cvl, __lexp, 16.0, 4);
+ __LO_EXP (__cvl, __lexp, 4.0, 2);
+ __LO_EXP (__cvl, __lexp, 2.0, 1);
+#undef __LO_EXP
+ }
+ /* now we loop until the next t's is more than EGLPNUM_MINEPS */
+ /* the formula is
+ * p_i = t_i*p_{i-1} + p_{i-2}, and
+ * q_i = t_i*q_{i-1} + q_{i-2}
+ * note that |x-p_i/q_i|<1/q_i^2
+ * for us t_i = __utmp, and the current number is either [0,1,2] in the __z
+ * array, we use those popsitions ciclicly, and use the four position as a
+ * temporary number, __z+4 is used to store q's, at the beginning i = 1. */
+ while (1)
+ {
+ if (__cvl < EGLPNUM_MINEPS || (mpz_cmp_ui (__z[4], (unsigned long int)0xfffffff) > 0))
+ {
+ mpz_set (mpq_denref (var), __z[4]);
+ mpz_set (mpq_numref (var), __z[1]);
+ break;
+ }
+ MESSAGE(MPQ_VERBOSE_CNT_FRAC,"cur approximate %ld/%ld, error %10.7lg",
+ mpz_get_si(__z[1]), mpz_get_si(__z[4]), __cvl);
+ /* first run */
+ __cvl = 1 / __cvl;
+ __dbl = floor(__cvl);
+ __utmp = (unsigned long)__dbl;
+ __cvl -= __dbl;
+ mpz_set_ui (__z[6], __utmp);
+ mpz_set (__z[2], __z[0]);
+ mpz_addmul (__z[2], __z[1], __z[6]);
+ mpz_set (__z[5], __z[3]);
+ mpz_addmul (__z[5], __z[4], __z[6]);
+ if (__cvl < EGLPNUM_MINEPS || (mpz_cmp_ui (__z[5], (unsigned long int)0xfffffff) > 0))
+ {
+ mpz_set (mpq_denref (var), __z[5]);
+ mpz_set (mpq_numref (var), __z[2]);
+ break;
+ }
+ MESSAGE(MPQ_VERBOSE_CNT_FRAC,"cur approximate %ld/%ld, error %10.7lg",
+ mpz_get_si(__z[2]), mpz_get_si(__z[5]), __cvl);
+ /* second run */
+ __cvl = 1 / __cvl;
+ __dbl = floor(__cvl);
+ __utmp = (unsigned long)(__dbl);
+ __cvl -= __dbl;
+ mpz_set_ui (__z[6], __utmp);
+ mpz_set (__z[0], __z[1]);
+ mpz_addmul (__z[0], __z[2], __z[6]);
+ mpz_set (__z[3], __z[4]);
+ mpz_addmul (__z[3], __z[5], __z[6]);
+ if (__cvl < EGLPNUM_MINEPS || (mpz_cmp_ui (__z[3], (unsigned long int)0xfffffff) > 0))
+ {
+ mpz_set (mpq_denref (var), __z[3]);
+ mpz_set (mpq_numref (var), __z[0]);
+ break;
+ }
+ MESSAGE(MPQ_VERBOSE_CNT_FRAC,"cur approximate %ld/%ld, error %10.7lg",
+ mpz_get_si(__z[0]), mpz_get_si(__z[3]), __cvl);
+ /* third run */
+ __cvl = 1 / __cvl;
+ __dbl = floor(__cvl);
+ __utmp = (unsigned long)(__dbl);
+ __cvl -= __dbl;
+ mpz_set_ui (__z[6], __utmp);
+ mpz_set (__z[1], __z[2]);
+ mpz_addmul (__z[1], __z[0], __z[6]);
+ mpz_set (__z[4], __z[5]);
+ mpz_addmul (__z[4], __z[3], __z[6]);
+ }
+ for (__utmp = 7; __utmp--;)
+ mpz_clear (__z[__utmp]);
+ }
+ /* ending */
+ mpq_canonicalize (var);
+ if (__lsgn)
+ mpq_neg (var, var);
+ if (__lexp > 0)
+ mpq_mul_2exp (var, var, (unsigned long int) __lexp);
+ if (__lexp < 0)
+ mpq_div_2exp (var, var, (unsigned long int) (-__lexp));
+ return;
+}
+
+/* ========================================================================= */
+int mpz_EGlpNumReadStr (mpz_t var,
+ char const *str)
+{
+ /* local variables */
+ char unsigned a_sgn = 1;
+ char unsigned sgn = 0;
+ char c = 0;
+ int n_char = 0;
+ /* now we read the string */
+ c = str[n_char];
+ mpz_set_ui (var, (unsigned long int)0);
+ while ((('0' <= c) && (c <= '9')) || /* allow to read digits */
+ (a_sgn && (c == '+' || c == '-')) /* allow sign for exponent */ )
+ {
+ switch (c)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ mpz_mul_ui (var, var, (unsigned long int)10);
+ mpz_add_ui (var, var, (unsigned long int)(c - '0'));
+ a_sgn = 0;
+ break;
+ case '-':
+ sgn = 1;
+ case '+':
+ a_sgn = 0;
+ break;
+ }
+ /* advance the reading character */
+ c = str[++n_char];
+ }
+ if (sgn)
+ mpz_neg (var, var);
+ return n_char;
+}
+
+/* ========================================================================= */
+int mpq_EGlpNumReadStrXc (mpq_t var,
+ char const *str)
+{
+ /* local variables */
+ char unsigned a_dot = 1,
+ a_exp = 0,
+ a_exp_sgn = 0,
+ a_sgn = 1,
+ a_div = 1;
+ char c = 0;
+ int l_exp = 0,
+ sgn = 0,
+ exp_sgn = 0;
+ int n_char = 0,
+ n_dig = 0,
+ cn = 0;
+ mpq_t den[2];
+ mpq_init (den[0]);
+ mpq_init (den[1]);
+ mpq_set_ui (den[1], (unsigned long int)1, (unsigned long int)1);
+ mpq_set_ui (den[0], (unsigned long int)0, (unsigned long int)1);
+
+ /* now we read the string */
+ c = str[n_char];
+ while ((('0' <= c) && (c <= '9')) || /* allow to read digits */
+ (a_dot && (c == '.')) || /* allow to read a dot point */
+ (a_exp && (c == 'e' || c == 'E')) || /* allow an exponent marker */
+ (a_sgn && (c == '+' || c == '-')) || /* allow a number sign */
+ (a_div && c == '/') || /* allow the division sign */
+ (a_exp_sgn && (c == '+' || c == '-')) /* allow sign for exponent */ )
+ {
+ switch (c)
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ /* if we haven't read the exponent then the digits bellongs to the mantisa
+ * */
+ if (a_exp || n_dig == 0)
+ {
+ if (!a_dot)
+ mpz_mul_ui (mpq_denref (den[cn]), mpq_denref (den[cn]), (unsigned long int)10);
+ mpz_mul_ui (mpq_numref (den[cn]), mpq_numref (den[cn]), (unsigned long int)10);
+ mpz_add_ui (mpq_numref (den[cn]), mpq_numref (den[cn]),
+ (unsigned long int)(c - '0'));
+ n_dig++;
+ a_exp = 1;
+ }
+ /* otherwise, if we have read the exponent, the digits should go to the
+ * exponent */
+ else
+ {
+ l_exp = 10 * l_exp + c - '0';
+ a_exp_sgn = 0;
+ }
+ a_sgn = 0;
+ break;
+ case '.':
+ a_sgn = 0;
+ a_dot = 0;
+ a_sgn = 0;
+ break;
+ case '-':
+ if (a_sgn)
+ sgn = 1;
+ else
+ exp_sgn = 1;
+ case '+':
+ if (a_sgn)
+ a_sgn = 0;
+ if (a_exp_sgn)
+ a_exp_sgn = 0;
+ break;
+ case 'e':
+ case 'E':
+ a_sgn = 0;
+ a_exp = 0;
+ a_exp_sgn = 1;
+ break;
+ case '/':
+ if (exp_sgn)
+ l_exp = -l_exp;
+ if (l_exp > 0)
+ while (l_exp--)
+ mpz_mul_ui (mpq_numref (den[0]), mpq_numref (den[0]), (unsigned long int)10);
+ else if (l_exp < 0)
+ {
+ l_exp = -l_exp;
+ while (l_exp--)
+ mpz_mul_ui (mpq_denref (den[0]), mpq_denref (den[0]), (unsigned long int)10);
+ }
+ if (sgn)
+ mpz_neg (mpq_numref (den[0]), mpq_numref (den[0]));
+ mpq_canonicalize (den[0]);
+ mpq_set_ui (den[1], (unsigned long int)0, (unsigned long int)1);
+ sgn = 0;
+ exp_sgn = 0;
+ l_exp = 0;
+ a_div = 0;
+ n_dig = 0;
+ a_dot = 1;
+ a_exp = 0;
+ a_exp_sgn = 0;
+ a_sgn = 1;
+ cn = 1;
+ break;
+ }
+ /* advance the reading character */
+ c = str[++n_char];
+ }
+ if (n_char)
+ {
+ /* now expand the exponent of the denominator */
+ if (exp_sgn)
+ l_exp = -l_exp;
+ if (l_exp > 0)
+ while (l_exp--)
+ mpz_mul_ui (mpq_numref (den[cn]), mpq_numref (den[cn]), (unsigned long int)10);
+ else if (l_exp < 0)
+ {
+ l_exp = -l_exp;
+ while (l_exp--)
+ mpz_mul_ui (mpq_denref (den[cn]), mpq_denref (den[cn]), (unsigned long int)10);
+ }
+ /* check the sign of the whole number */
+ if (sgn)
+ mpz_neg (mpq_numref (den[cn]), mpq_numref (den[cn]));
+ /* ending */
+ mpq_canonicalize (den[0]);
+ mpq_canonicalize (den[1]);
+ mpq_div (var, den[0], den[1]);
+ }
+ mpq_clear (den[0]);
+ mpq_clear (den[1]);
+ return n_char;
+}
+
+/* ========================================================================= */
+void uint32_EGutilPermSort (const size_t sz,
+ int *const perm,
+ const uint32_t * const elem)
+{
+ size_t i,
+ j;
+ int temp;
+ uint32_t t;
+ if (sz <= 1)
+ return;
+
+ EGswap (perm[0], perm[(sz - 1) / 2], temp);
+ i = 0;
+ j = sz;
+ (t= elem[perm[0]]);
+ for (;;)
+ {
+ do
+ i++;
+ while (i < sz && (elem[perm[i]]< t));
+ do
+ j--;
+ while (j && (t< elem[perm[j]]));
+ if (j < i)
+ break;
+ EGswap (perm[i], perm[j], temp);
+ }
+ EGswap (perm[0], perm[j], temp);
+ uint32_EGutilPermSort (j, perm, elem);
+ uint32_EGutilPermSort (sz - i, perm + i, elem);
+}
+
+/* ========================================================================= */
+void uint32_EGutilPermSort2 (const size_t sz,
+ int *const perm,
+ const uint32_t * const elem)
+{
+ size_t i,
+ j;
+ int temp;
+ uint32_t t;
+ if (sz <= 1)
+ return;
+
+ EGswap (perm[0], perm[(sz - 1) / 2], temp);
+ i = 0;
+ j = sz;
+ (t= elem[perm[0]]);
+ for (;;)
+ {
+ do
+ i++;
+ while (i < sz && (t< elem[perm[i]]));
+ do
+ j--;
+ while ((elem[perm[j]]< t));
+ if (j < i)
+ break;
+ EGswap (perm[i], perm[j], temp);
+ }
+ EGswap (perm[0], perm[j], temp);
+ uint32_EGutilPermSort2 (j, perm, elem);
+ uint32_EGutilPermSort2 (sz - i, perm + i, elem);
+}
+
+/* ========================================================================= */
+/** @} */
diff --git a/qsopt_ex/eg_lpnum.dbl.h b/qsopt_ex/eg_lpnum.dbl.h
new file mode 100644
index 0000000..48e8faa
--- /dev/null
+++ b/qsopt_ex/eg_lpnum.dbl.h
@@ -0,0 +1,488 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ *
+ * 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
+ * */
+#ifndef __EG_LPNUM_DBL__
+#define __EG_LPNUM_DBL__
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <float.h>
+
+#include "eg_lpnum.h"
+
+/** @file
+ * @ingroup EGlpNum */
+/** @addtogroup EGlpNum */
+/** @{ */
+/* ========================================================================= */
+/** extern definitions of constaants for different set-ups */
+#define dbl_zeroLpNum 0.0
+#define dbl_oneLpNum 1.0
+#define dbl_epsLpNum DBL_EPSILON
+#define dbl_MaxLpNum DBL_MAX
+#define dbl_MinLpNum DBL_MIN
+
+/* ========================================================================= */
+/** @brief Read from a string a number and store it in the given double,
+ * @return the number of chars readed from the input string */
+#define dbl_EGlpNumReadStr(a,str) ({\
+ int __i =0;\
+ sscanf(str,"%lf%n",&(a),&__i);\
+ __i;})
+
+/* ========================================================================= */
+/** @brief given a double, write it to a string (to be allocated internally),
+ * and return it. */
+#define dbl_EGlpNumGetStr(a) ({\
+ char *__str=0;\
+ int __i=snprintf(__str,(size_t)0,"%.7lg",a);\
+ __str = EGsMalloc(char,__i+1);\
+ snprintf(__str,(size_t)(__i+1),"%.7lg",a);\
+ __str;})
+
+/* ========================================================================= */
+/** @brief given an array of type double, free it, if the pointer is NULL
+ * nothing happen. */
+#define dbl_EGlpNumFreeArray(ea) __EGlpNumFreeArray(ea)
+
+/* ========================================================================= */
+/** @brief Reallocate and initialize (if needed) 'size' elements of type
+ * EGlpNum_t and return it, if no more memory, exit(1) */
+#define dbl_EGlpNumReallocArray(lptr, lsize) ({\
+ size_t __csz = (lsize), *__usp = 0;\
+ size_t __psz = __EGlpNumArraySize(*lptr);\
+ double** __ptr__ = (lptr);\
+ if (!__psz) *__ptr__ = dbl_EGlpNumAllocArray (__csz); \
+ else if (__psz < __csz) {\
+ __usp = (size_t*)(*__ptr__);\
+ __usp--;\
+ __usp = EGrealloc(__usp, sizeof(double)*__csz+sizeof(size_t));\
+ __usp[0] = __csz;\
+ *__ptr__ = (double*)(__usp+1);\
+ memset((*__ptr__)+__psz,0,sizeof(double)*(__csz-__psz));\
+ }\
+ *__ptr__;})
+
+/* ========================================================================= */
+/** @brief Allocate and initialize (if needed) 'size' elements of type double
+ * and return it, if no more memory, exit(1) */
+#define dbl_EGlpNumAllocArray(size) __EGlpNumAllocArray(double,size)
+
+/* ========================================================================= */
+/** @brief set the given number pointer, set its value to the given double.
+ * @param var double where we will store the double value.
+ * @param dbl double value to be stored in 'var'.
+ * @par Description:
+ * This function is intended to set initial values to variables; note that the
+ * double is a number and not a pointer to that value, be carefull with this
+ * detail. Also, due to implementation details this function can't deal with
+ * numbers above 1e158 or smaller than 1e-158. Note also that if the number is
+ * writen in the form \f$x=\bar{x}\cdot 2^e\f$ with \f$0.5<|\bar{x}|<1\f$,
+ * then \f$\left|x-\frac{p}{q}\right|<2^{e-64}\f$.
+ * */
+#define dbl_EGlpNumSet(var, dbl) ((var) = (dbl))
+
+/* ========================================================================= */
+/** @brief Stores in the first number the ceil value of the second number, i.e.
+ * EGlpNumCeil(a,b) <==> a= ceil(b) */
+#define dbl_EGlpNumCeil(a, b) ((a) = ceil(b))
+
+/* ========================================================================= */
+/** @brief Stores in the first number the floor value of the second number, i.e.
+ * EGlpNumFloor(a,b) <==> a= floor(b) */
+#define dbl_EGlpNumFloor(a, b) ((a) = floor(b))
+
+/* ========================================================================= */
+/** @brief store the (multiplicative) inverse of a number to itself, i.e.
+ * implement a = 1/a.
+ * @param a the number to be inverted. */
+#define dbl_EGlpNumInv(a) ((a) = 1.0/(a))
+
+/* ========================================================================= */
+/** @brief Compare if two numbers are equal within a maximum error.
+ * @param a EGlpNum_t first number to compare.
+ * @param b EGlpNum_t second number to compare.
+ * @return int one in success, zero oterwise.
+ * @par Description:
+ * Given two numbers 'a','b' return 1 if a == b, otherwise it return 0
+ * */
+#define dbl_EGlpNumIsEqqual(a,b) ((a) == (b))
+
+/* ========================================================================= */
+/** @brief Compare if two numbers are equal within a maximum error.
+ * @param a EGlpNum_t first number to compare.
+ * @param b EGlpNum_t second number to compare.
+ * @param error EGlpNum_t maximum difference allowed between both
+ * numbers.
+ * @return int one in success, zero oterwise.
+ * @par Description:
+ * Given two numbers 'a','b' and a tolerance 'error',
+ * return 1 if |a-b|<= error, otherwise it return 0.
+ * */
+#define dbl_EGlpNumIsEqual(a,b,error) (fabs((a)-(b)) <= (error))
+#define dbl_EGlpNumIsNeq(a,b,error) (((a)-(b) > (error)) || ((b)-(a) > (error)))
+#define dbl_EGlpNumIsNeqq(a,b) ((a) != (b))
+#define dbl_EGlpNumIsNeqZero(a,error) (((a) > (error)) || (-(a) > (error)))
+#define dbl_EGlpNumIsNeqqZero(a) ((a) != 0.0)
+
+/* ========================================================================= */
+/** @brief test if the first number is greater than zero
+ * @param a EGlpNum_t number to test.
+ * @return int one if success, zero otherwise.
+ * */
+#define dbl_EGlpNumIsGreatZero(a) (a > 0.0)
+
+/* ========================================================================= */
+/** @brief test if the first number is less than zero
+ * @param a EGlpNum_t number to test.
+ * @return int one if success, zero otherwise.
+ * */
+#define dbl_EGlpNumIsLessZero(a) (a < 0.0)
+
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a EGlpNum_t the first number.
+ * @param b EGlpNum_t the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a < b, zero
+ * otherwise.
+ * */
+#define dbl_EGlpNumIsLess(a,b) (a < b)
+
+/* ========================================================================= */
+/** @brief test if the sum of the first two numbers is less thatn the third
+ * number.
+ * @param a EGlpNum_t the first number.
+ * @param b EGlpNum_t the second number
+ * @param c EGlpNum_t the third number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given a,b, and c, return nonzero if (a + b < c), zero toherwise.
+ * */
+#define dbl_EGlpNumIsSumLess(a, b, c) ((a) + (b) < (c))
+
+/* ========================================================================= */
+/** @brief test if the diference of the first two numbers is less thatn the
+ * third number.
+ * @param a EGlpNum_t the first number.
+ * @param b EGlpNum_t the second number
+ * @param c EGlpNum_t the third number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given a,b, and c, return nonzero if (a - b < c), zero toherwise.
+ * */
+#define dbl_EGlpNumIsDiffLess(a, b, c) ((a) - (b) < (c))
+
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a EGlpNum_t the first number.
+ * @param b double the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a < b, zero
+ * otherwise.
+ * */
+#define dbl_EGlpNumIsLessDbl(a,b) ((a) < (b))
+
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a EGlpNum_t the first number.
+ * @param b double the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a > b, zero
+ * otherwise.
+ * */
+#define dbl_EGlpNumIsGreaDbl(a,b) ((a) > (b))
+
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a EGlpNum_t the first number.
+ * @param b EGlpNum_t the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a <= b, zero
+ * otherwise.
+ * */
+#define dbl_EGlpNumIsLeq(a,b) ((a) <= (b))
+
+/* ========================================================================= */
+/** @brief copy the value of the second number to the first.
+ * @param a EGlpNum_t source number (it won't change value).
+ * @param b EGlpNum_t source number (it won't change value).
+ * @param den EGlpNum_t denominator of the difference (it won't change value).
+ * @param dest EGlpNum_t where to store the value .
+ * @par Description:
+ * Set dest = (a - b) / den */
+#define dbl_EGlpNumCopyDiffRatio(dest,a, b, den) ((dest) = ((a) - (b)) / (den))
+
+/* ========================================================================= */
+/** @brief copy the value of the second number to the first.
+ * @param a EGlpNum_t source number (it won't change value).
+ * @param b EGlpNum_t source number (it won't change value).
+ * @param dest EGlpNum_t where to store the value stored in 'orig'.
+ * @par Description:
+ * Set dest = a - b */
+#define dbl_EGlpNumCopyDiff(dest,a,b) ((dest) = (a) - (b))
+
+/* ========================================================================= */
+/** @brief copy the value of the sum of the second and third parameter
+ * @param a EGlpNum_t source number (it won't change value).
+ * @param b EGlpNum_t source number (it won't change value).
+ * @param dest EGlpNum_t where to store the sum.
+ * @par Description:
+ * Set dest = a + b */
+#define dbl_EGlpNumCopySum(dest,a,b) ((dest) = (a) + (b))
+
+/* ========================================================================= */
+/** @brief copy the value of the second number to the first.
+ * @param orig EGlpNum_t source number (it won't change value).
+ * @param dest EGlpNum_t where to store the value stored in 'orig'.
+ * @par Description:
+ * Given two numbers copy the values in 'orig', into 'dest'.
+ * */
+#define dbl_EGlpNumCopy(dest,orig) ((dest) = (orig))
+
+/* ========================================================================= */
+/** @brief change the fist number to the maximum between itself and the
+ * absolute value of the second.
+ * @param orig EGlpNum_t source number (it won't change value).
+ * @param dest EGlpNum_t where to store the value stored in 'orig'.
+ * @par Description:
+ * implement dest = max(dest,abs(orig))
+ * */
+#define dbl_EGlpNumSetToMaxAbs(dest, orig) if((dest) < fabs(orig)) \
+ (dest) = fabs(orig)
+#define dbl_EGlpNumSetToMinAbs(dest, orig) if((dest) > fabs(orig)) \
+ (dest) = fabs(orig)
+
+/* ========================================================================= */
+/** @brief copy the square of the second argument, divided by the third
+ * argument into the first argument.
+ * @param dest EGlpNum_t where to store the result
+ * @param orig EGlpNum_t second parameter
+ * @param den EGlpNum_t third parameter
+ * @par Description:
+ * compute dest = (orig*orig)/den
+ * */
+#define dbl_EGlpNumCopySqrOver(dest, orig, den) ((dest) = (orig)*(orig)/(den))
+
+/* ========================================================================= */
+/** @brief copy the value of the absolute value of the second parameter to the
+ * first parameter.
+ * @param orig EGlpNum_t source number (it won't change value).
+ * @param dest EGlpNum_t where to store the absolute value stored
+ * in 'orig'.
+ * @par Description:
+ * Given a number 'orig', copy its absolute value to 'dest'. i.e.
+ * dest = |orig|
+ * */
+#define dbl_EGlpNumCopyAbs(dest,orig) ((dest) = fabs(orig))
+
+/* ========================================================================= */
+/** @brief copy minus the value of the second parameter to the
+ * first parameter.
+ * @param orig EGlpNum_t the source number (it won't change value).
+ * @param dest EGlpNum_t where to store minus the value stored
+ * in 'orig'.
+ * @par Description:
+ * Given a number 'orig', copy minus the value to 'dest'. i.e.
+ * dest = -orig
+ * */
+#define dbl_EGlpNumCopyNeg(dest,orig) ((dest) = -(orig))
+
+/* ========================================================================= */
+/** @brief Set des = op1/op2.
+ * @param dest EGlpNum_t where we will store the result.
+ * @param op1 EGlpNum_t numerator of the fraction (possibly non an integer)
+ * @param op2 EGlpNum_t denominator of the fraction (possibly non an integer)
+ * @par Description:
+ * Set des = op1/op2
+ * */
+#define dbl_EGlpNumCopyFrac(dest,op1,op2) ((dest) = (op1)/(op2))
+
+/* ========================================================================= */
+/** @brief copy the first 'size' values in the second array to the first array.
+ * @param orig EGlpNum_t* pointer to the array from where we will copy the
+ * values (it won't change value).
+ * @param dest EGlpNum_t* pointer to where to store the first 'size' values
+ * stored in 'orig'.
+ * @param size unsigned int specifying how many values of 'orig' will be copied
+ * onto 'dest'
+ * @par Description:
+ * This function is provided to (possible) make fast copies of arrays of
+ * numbers, the arrays should be of length at least 'size', and the resulting
+ * copy is absolutely independent froom the original, any change in one vale of
+ * one array won't change values on the other array.
+ * */
+#define dbl_EGlpNumCopyArray(dest,orig,size) memcpy(dest,orig,sizeof(double)*(size))
+
+/* ========================================================================= */
+/** @brief Sub to a given number the product of two numbers.
+ * @param a EGlpNum_t the number that we are going to Sub to.
+ * @param b EGlpNum_t value to be multiplyed.
+ * @param c EGlpNum_t value to be multiplyed.
+ * @par Description:
+ * This function implements a = a - b*c, and clearly don't change the value
+ * stored in 'b' nor in 'c'.
+ * */
+#define dbl_EGlpNumSubInnProdTo(a, b, c) ((a) -= (b)*(c))
+
+/* ========================================================================= */
+/** @brief Add to a given number the product of two numbers.
+ * @param a EGlpNum_t the number that we are going to add to.
+ * @param b EGlpNum_t value to be multiplyed.
+ * @param c EGlpNum_t value to be multiplyed.
+ * @par Description:
+ * This function implements a = a + b*c, and clearly don't change the value
+ * stored in 'b' nor in 'c'.
+ * */
+#define dbl_EGlpNumAddInnProdTo(a, b, c) ((a) += (b)*(c))
+
+/* ========================================================================= */
+/** @brief Substract to a given number the value of the second number.
+ * @param a EGlpNum_t the number that we are going to substract to.
+ * @param b unsigned int value to be substracted to 'a'.
+ * @par Description:
+ * This function implements a = a - b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define dbl_EGlpNumSubUiTo(a,b) ((a) -= (b))
+
+/* ========================================================================= */
+/** @brief Add to a given number the value of the second number.
+ * @param a EGlpNum_t the number that we are going to add to.
+ * @param b unsigned int value to be added to 'a'.
+ * @par Description:
+ * This function implements a = a + b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define dbl_EGlpNumAddUiTo(a,b) ((a) += (b))
+
+/* ========================================================================= */
+/** @brief Add to a given number the value of the second number.
+ * @param a EGlpNum_t the number that we are going to add to.
+ * @param b EGlpNum_t value to be added to 'a'.
+ * @par Description:
+ * This function implements a = a + b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define dbl_EGlpNumAddTo(a,b) ((a) += (b))
+
+/* ========================================================================= */
+/** @brief Substract to a given number the value of the second number.
+ * @param a EGlpNum_t the number that we are going to substract
+ * from.
+ * @param b EGlpNum_t value to be substracted to 'a'.
+ * @par Description:
+ * This function implements a = a - b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define dbl_EGlpNumSubTo(a,b) ((a) -= (b))
+
+/* ========================================================================= */
+/** @brief Multiply a given number by the value of the second number.
+ * @param a EGlpNum_t the number that we are going to multiply by
+ * the second number and store the result.
+ * @param b EGlpNum_t value to be multyply to 'a'.
+ * @par Description:
+ * This function implements a = a * b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define dbl_EGlpNumMultTo(a,b) ((a) *= (b))
+
+/* ========================================================================= */
+/** @brief Divide a given number by the value of the second number.
+ * @param a EGlpNum_t the number that we are going to divide by
+ * the second number and store the result.
+ * @param b EGlpNum_t value to be divide to 'a'.
+ * @par Description:
+ * This function implements a = a / b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define dbl_EGlpNumDivTo(a,b) ((a) /= (b))
+
+/* ========================================================================= */
+/** @brief Divide a given number by the value of the second number.
+ * @param a EGlpNum_t the number that we are going to divide by
+ * the second number and store the result.
+ * @param b unsigned int value to be divided to 'a'.
+ * @par Description:
+ * This function implements a = a / b, and don't change the value
+ * stored in 'b'.
+ * */
+#define dbl_EGlpNumDivUiTo(a,b) ((a) /= (b))
+
+/* ========================================================================= */
+/** @brief Multiply a given number by the value of the second number.
+ * @param a EGlpNum_t the number that we are going to multiply by
+ * the second number and store the result.
+ * @param b unsigned int value to be multyply to 'a'.
+ * @par Description:
+ * This function implements a = a * b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define dbl_EGlpNumMultUiTo(a,b) ((a) *= (b))
+
+/* ========================================================================= */
+/** @brief Reset the value of the pointed number to zero.
+ * @param a EGlpNum_t the value to be set to zero.
+ * @par Descrpition:
+ * Reset a to zero, i.e. implements a = 0;
+ * */
+#define dbl_EGlpNumZero(a) ((a) = 0.0)
+
+/* ========================================================================= */
+/** @brief Reset the value of the pointed number to one.
+ * @param a EGlpNum_t value to be set to one.
+ * @par Descrpition:
+ * Reset a to zero, i.e. implements a = 1;
+ * */
+#define dbl_EGlpNumOne(a) ((a) = 1.0)
+
+/* ========================================================================= */
+/** @brief Change the sign of the number.
+ * @param a EGlpNum_t number we will change sign.
+ * @par Descrpition:
+ * Change the sign of the given number, i.e. implements a = -a
+ * */
+#define dbl_EGlpNumSign(a) ((a) = -(a))
+
+/* ========================================================================= */
+/** @brief return the closest double value of the given pointer number.
+ * @param a EGlpNum_t number that we will be transformed to double.
+ * @return double the closest double representation of the given number.
+ * par Description:
+ * return the double number closest in value to the value stored in a.
+ * */
+#define dbl_EGlpNumToLf(a) ((double)a)
+
+/* ========================================================================= */
+/** @brief initialize the internal memory of a given variable */
+#define dbl_EGlpNumInitVar(a) dbl_EGlpNumZero(a)
+
+/* ========================================================================= */
+/** @brief free the internal memory of a given variable */
+#define dbl_EGlpNumClearVar(a)
+
+/* ========================================================================= */
+/** @} */
+#endif
diff --git a/qsopt_ex/eg_lpnum.h b/qsopt_ex/eg_lpnum.h
new file mode 100644
index 0000000..3a90fbd
--- /dev/null
+++ b/qsopt_ex/eg_lpnum.h
@@ -0,0 +1,706 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ *
+ * 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
+ * */
+#ifndef __EG_LPNUM_H__
+#define __EG_LPNUM_H__
+/* ========================================================================= */
+/** @defgroup EGlpNum EGlpNum
+ *
+ * Here we define a common interface to handle numbers in general, the idea is
+ * to be able to work with infinite precicion numbers, plain doubles, floats,
+ * integers, or fixed point numbers, without actually making different codes
+ * for each of those types, rather we preffer to fix that at compyle time.
+ *
+ * @par History:
+ * Revision 1.1.0
+ * - 2013-04-18
+ * - Add uint32_EGutilPermSort and uint32_EGutilPermSort2
+ * - 2010-09-02
+ * - Add support for int32 templates, streamline the template
+ * implementation too
+ * - Add MaxLpNum and MinLpNum keywords
+ * We start doing the migration to gmp and 'natural' types, this means that we
+ * drop support for EGrat, this allow us to drop the requirement to use
+ * pointers, and instead we can just call the functions with the original
+ * parameters, still we have to be VERY carefull regarding changing
+ * local/external copies.
+ * - 2007-10-08
+ * - Move EGswap, EGabs, EGmin and Egmax to eg_numutil.h
+ * - 2005-10-31
+ * - Add EGswap to swap elements of any predefined type.
+ * - 2005-08-31
+ * - Add EGmin and EGmax for built in types (i.e. for types where
+ * the < comparison works as we want).
+ * - 2005-08-16
+ * - Streamline mpq_EGlpNumGetStr
+ * - Minor Fixes for zeroLpNum
+ * - 2005-07-29
+ * - Add EGabs definition.
+ * - 2005-07-24
+ * - Split eg_lpnum.h into different headers for each type of
+ * suported numbers.
+ * - Deprecate EGlpNumCOmpUFrac
+ * - 2005-05-26
+ * - Add epsLpNum
+ * - 2005-05-17
+ * - Add mpq_EGlpNumReadStrXc(mpq_t,__EGPstr__)
+ * - 2005-05-16
+ * - Add mpq_EGlpNumSet_mpf(mpq,mpf)
+ * - 2005-05-12
+ * - Add mpf_EGlpNumEpow(num,power)
+ * - Add function to change precision of the numbers on the fly.
+ * - Add EGlpNumReadStr to set a number from a given input string.
+ * - Add EGlpNumGetStr to get (hopefully) the exact representation
+ * of the given input as string.
+ * - 2005-05-03
+ * - Change the structure of the header so it provides an interface
+ * in which a program can use all types of numbers at the same time,
+ * this implies that we must define a start-up and clean-up function
+ * that would initialize all constants for all numbers, and change
+ * the naming scheme accordingly to support this.
+ * - Deprecate EGlpNumInitArray
+ * - Deprecate EGlpNumFreeIntArray
+ * - Change all static-inline definitions to Statement Exprs style.
+ * - 2005-04-25
+ * - Add EGlpNumIsSumLess(__EGPa__,__EGPb__,__EGPc__)
+ * - Add EGlpNumIsDiffLess(__EGPa__,__EGPb__,__EGPc__)
+ * - 2005-04-13
+ * - Add EGlpNumCopyDiffRatio(__EGPa__,__EGPb__,__EGPc__,d)
+ * - Add EGlpNumIsEqqual(__EGPa__,__EGPb__)
+ * - Add EGlpNumIsEqual(__EGPa__,__EGPb__,__EGPerr__)
+ * - Add EGlpNumCopy(__EGPa__,__EGPb__)
+ * - Add EGlpNumIsLess(__EGPa__,__EGPb__)
+ * - Add EGlpNumToLf(__EGPa__)
+ * - Add EGlpNumCopyDiff(__EGPa__,__EGPb__,__EGPc__)
+ * - Add EGlpNumCopyAbs(__EGPa__,__EGPb__)
+ * - Add EGlpNumSubTo(__EGPa__,__EGPb__)
+ * - Add EGlpNumAddTo(__EGPa__,__EGPb__)
+ * - Add EGlpNumDivTo(__EGPa__,__EGPb__)
+ * - Add EGlpNumMultTo(__EGPa__,__EGPb__)
+ * - Add EGlpNumZero(__EGPa__)
+ * - Add EGlpNumOne(__EGPa__)
+ * - Add EGlpNumAddInnProdTo(__EGPa__,__EGPb__,__EGPc__)
+ * - Add EGlpNumSubInnProdTo(__EGPa__,__EGPb__,__EGPc__)
+ * - Add EGlpNumSign(__EGPa__)
+ * - Add EGlpNumCopyNeg(__EGPa__,__EGPb__)
+ * - Add EGlpNumDivUiTo(__EGPa__,__EGPb__)
+ * - Add EGlpNumMultUiTo(__EGPa__,__EGPb__)
+ * - Add EGlpNumIsLeq(__EGPa__,__EGPb__)
+ * - Add EGlpNumCopySqrOver(__EGPa__,__EGPb__,__EGPc__)
+ * - Add EGlpNumSet(__EGPa__,__EGPb__)
+ * - Add EGlpNumCopyFrac(__EGPa__,__EGPb__,__EGPc__)
+ * - Add EGlpNumAddUiTo(__EGPa__,__EGPb__)
+ * - Add EGlpNumSubUiTo(__EGPa__,__EGPb__)
+ * - Add EGlpNumCopySum(__EGPa__,__EGPb__,__EGPc__)
+ * - Add EGlpNumInv(__EGPa__)
+ * - Add EGlpNumFloor(__EGPa__)
+ * - Add EGlpNumCeil(__EGPa__)
+ * - Add EGlpNumIsLessDbl(__EGPa__,__EGPb__)
+ * - Add EGlpNumIsGreaDbl(__EGPa__,__EGPb__)
+ * - Add EGlpNumSetToMaxAbs(__EGPa__,__EGPb__)
+ * - Add EGlpNumAllocArray(__EGPszb__)
+ * - Add EGlpNumFreeArray(__EGPa__)
+ * - Add EGlpNumReallocArray(__EGPa__,__EGPszb__)
+ * - Add EGlpNumInitVar(__EGPa__)
+ * - Add EGlpNumClearVar(__EGPa__)
+ * - Add EGlpNumIsNeqq(__EGPa__,__EGPb__)
+ * - Add EGlpNumIsNeq(__EGPa__,__EGPb__,__EGPc__)
+ * - Add EGlpNumIsNeqqZero(__EGPa__)
+ * - Add EGlpNumIsNeqZero(__EGPa__,__EGPb__)
+ * - Add EGlpNumSetToMinAbs(__EGPa__,__EGPb__)
+ * Revision 0.0.1
+ * - 2004-07-15
+ * - Add support for GNU_MP_F types
+ * - 2004-07-14
+ * - Add support for GNU_MP_Q types
+ * - 2004-07-12
+ * - Add support for EG-rationals
+ * - 2004-06-21
+ * - First Implementation/Definition
+ * */
+
+/** @file
+ * @ingroup EGlpNum */
+/** @addtogroup EGlpNum */
+/** @{ */
+/* ========================================================================= */
+
+#include <stdlib.h>
+#include <stdint.h>
+
+#include <gmp.h>
+
+/* ========================================================================= */
+/** @name Number Types Definitions:
+ * Define (as its name suggest) an internal identifier for the given
+ * type. this definitions are provided to select different types of data at
+ * compile time, thus allowing us to provide limited template support. */
+/* @{ */
+/** C double type. */
+#define DBL_TYPE 0
+/** C float type. */
+#define FLT_TYPE 1
+/** C int type. */
+#define INT_TYPE 2
+/** EGlib #EGfp10_t type, this is an implementation of fixed precision
+ * arithmetic with 10 bits for fractional representation. */
+#define FP10_TYPE 3
+/** EGlib #EGfp20_t type, this is an implementation of fixed precision
+ * arithmetic with 20 bits for fractional representation. */
+#define FP20_TYPE 4
+/** EGlib #EGfp28_t type, this is an implementation of fixed precision
+ * arithmetic with 28 bits for fractional representation. */
+#define FP28_TYPE 5
+/** EGlib #EGfp25_t type, this is an implementation of fixed precision
+ * arithmetic with 25 bits for fractional representation. */
+#define FP25_TYPE 6
+/** GNU_MP library mpz_t type */
+#define GNU_MP_Z 8
+/** GNU_MP library mpq_t type */
+#define GNU_MP_Q 9
+/** GNU_MP library mpf_t type */
+#define GNU_MP_F 10
+/** C long double type */
+#define LDBL_TYPE 11
+/** C long long int type */
+#define LLINT_TYPE 12
+/** SoftFloat 128-bit floating point numbner */
+#define FLOAT128_TYPE 13
+/** int32_t integers */
+#define INT32_TYPE 14
+/* @} */
+/* ========================================================================= */
+
+/* We have no mpz specific header so we include these here */
+extern const mpz_t __zeroLpNum_mpz__;
+extern const mpz_t __oneLpNum_mpz__;
+extern const mpz_t __MaxLpNum_mpz__;
+extern const mpz_t __MinLpNum_mpz__;
+#define mpz_zeroLpNum __zeroLpNum_mpz__
+#define mpz_oneLpNum __oneLpNum_mpz__
+#define mpz_epsLpNum __zeroLpNum_mpz__
+#define mpz_MaxLpNum __MaxLpNum_mpz__
+#define mpz_MinLpNum __MinLpNum_mpz__
+
+#include "eg_lpnum.dbl.h"
+#include "eg_lpnum.mpq.h"
+#include "eg_lpnum.mpf.h"
+#include "eg_macros.h"
+#include "eg_mem.h"
+#include "eg_nummacros.h"
+/* ========================================================================= */
+/** @brief Debugging verbosity messages deped on the value of DEBUG (defined in
+ * eg_configure.h) and on the value of EGLPNUM_DEBUGL macro defined here.
+* */
+#define EGLPNUM_DEBUGL 100
+
+/* ========================================================================= */
+/** @brief Set the default number of __BITS__ used in the precision of the
+ * float point numbers (mpf_t), a normal double use up to 56-64 bits., the
+ * default precision is set to 128 */
+extern unsigned long int EGLPNUM_PRECISION;
+
+/* ========================================================================= */
+/** @brief Change the default precision for mpf_t numbers. */
+void EGlpNumSetPrecision (const unsigned prec);
+
+/* ========================================================================= */
+/** @brief Allocate an array of a given type and store (sizeof(size_t) bytes
+ * before the actual array) the size of the allocated array.
+ * @param __type the type of the array to be returned.
+ * @param __size the length of the array to be returned, note that it can be
+ * zero, in wich case no memory allocation is made and NULL is returned. */
+#define __EGlpNumAllocArray(__type,__size) ({\
+ size_t __sz = (__size);\
+ size_t *__utmp = __sz ? (size_t*) EGmalloc (sizeof(__type) * __sz + sizeof(size_t)) : 0;\
+ if(__sz) __utmp[0] = __sz;\
+ (__type*)(__sz ? (__utmp+1):0);})
+
+/* ========================================================================= */
+/** @brief Given an array allocated with __EGlpNumAllocArray, return the size of
+ * the given array, if the array is null, return zero.
+ * @param __array the array from where we need the size. */
+/* ========================================================================= */
+#define __EGlpNumArraySize(__array) ({\
+ size_t *__utmp = (size_t*)(__array);\
+ if(__utmp) __utmp--;\
+ __utmp ? __utmp[0]:0;})
+
+/* ========================================================================= */
+/** @brief, given an array allocated by __EGlpNumAllocArray, free the allocated
+ * memory.
+ * @param __array the array to be freed, it can be null. The given array will
+ * always pooint to NULL when this function is done.
+ * */
+/* ========================================================================= */
+#define __EGlpNumFreeArray(__array) ({\
+ size_t *__utmp = (size_t*)(__array);\
+ if(__utmp) free (__utmp-1);\
+ (__array) = 0;})
+
+/* ========================================================================= */
+/** @brief indicate if the global data needed for EGlpNum has been initialized,
+ * if zero, initialization routine should be called. This is provided to allow
+ * syncronization between libraries */
+extern int __EGlpNum_setup;
+/* ========================================================================= */
+/** @brief initialization routine for global data. This function is called as a
+ * constructor, but calling it twice won't cause any problems, it is provided
+ * to ensure that all EGlpnum globals are initialized at the beggining
+ * and in case they where not (__EGlpNMum_setup==0), then call the initializator */
+extern void EGlpNumStart(void);
+/* ========================================================================= */
+/** @brief This function must be called at the end of the program to free all
+ * internal data used in the EGlpNum_t structures, once this function is called
+ * any operation on EGlpNum_t types may fail.
+ * */
+extern void EGlpNumClear(void);
+/* ========================================================================= */
+/** @brief provided for backwards compatibility */
+#define EGlpNumExit EGlpNumClear
+/** @}*/
+/* ========================================================================= */
+/** @name Common EGlpNum Interface functions:
+ * Here we define the basic functions needed to declare when implementing a
+ * number template. */
+/** @{ */
+#ifdef UNUSED_INTERFACE
+/* ========================================================================= */
+/** extern definitions of constants for different set-ups */
+#define zeroLpNum
+#define oneLpNum
+#define epsLpNum
+#define MaxLpNum
+#define MinLpNum
+/* ========================================================================= */
+/** @brief Read from a string a number and store it in the given number,
+ * @return the number of chars readed from the input string */
+#define EGlpNumReadStr(__EGPa__,__EGPstr__)
+/* ========================================================================= */
+/** @brief given a int, write it to a string (to be allocated internally),
+ * and return it. */
+#define EGlpNumGetStr(__EGPa__)
+/* ========================================================================= */
+/** @brief given an array of type int, free it, if the pointer is NULL
+ * nothing happen. */
+#define EGlpNumFreeArray(__EGParr__)
+/* ========================================================================= */
+/** @brief Reallocate and initialize (if needed) 'size' elements of type
+ * EGlpNum_t and return it, if no more memory, exit(1) */
+#define EGlpNumReallocArray(__EGPptr__,__EGPsza__)
+/* ========================================================================= */
+/** @brief Allocate and initialize (if needed) 'size' elements of type int
+ * and return it, if no more memory, exit(1) */
+#define EGlpNumAllocArray(__EGPszb__)
+/* ========================================================================= */
+/** @brief set the given number, set its value to the given double.
+ * @param var where we will store the int value.
+ * @param dbl_var value to be stored in 'var'.
+ * @par Description:
+ * This function is intended to set initial values to variables; note that the
+ * int is a number and not a pointer to that value, be carefull with this
+ * detail. */
+#define EGlpNumSet(__EGPnum__,__EGPdnum__)
+/* ========================================================================= */
+/** @brief Stores in the first number the ceil value of the second number, i.e.
+ * EGlpNumCeil(__EGPa__,__EGPb__) <==> a= ceil(__EGPb__) */
+#define EGlpNumCeil(__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief Stores in the first number the floor value of the second number, i.e.
+ * EGlpNumFloor(__EGPa__,__EGPb__) <==> a= floor(__EGPb__) */
+#define EGlpNumFloor(__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief store the (multiplicative) inverse of a number to itself, i.e.
+ * implement a = 1/a.
+ * @param a the number to be inverted. */
+#define EGlpNumInv(__EGPa__)
+/* ========================================================================= */
+/** @brief Compare if two numbers are equal within a maximum error.
+ * @param a EGlpNum_t first number to compare.
+ * @param b EGlpNum_t second number to compare.
+ * @return int one in success, zero oterwise.
+ * @par Description:
+ * Given two numbers 'a','b' return 1 if a == b, otherwise it return 0
+ * */
+#define EGlpNumIsEqqual(__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief Compare if two numbers are equal within a maximum error.
+ * @param a EGlpNum_t first number to compare.
+ * @param b EGlpNum_t second number to compare.
+ * @param error EGlpNum_t maximum difference allowed between both
+ * numbers.
+ * @return int one in success, zero oterwise.
+ * @par Description:
+ * Given two numbers 'a','b' and a tolerance 'error',
+ * return 1 if |a-b| <= error, otherwise it return 0.
+ * */
+#define EGlpNumIsEqual(__EGPa__,__EGPb__,__EGPerr__)
+/* return 1 if |a-b| > error */
+#define EGlpNumIsNeq(__EGPa__,__EGPb__,__EGPerr__)
+/* return 1 if a == b */
+#define EGlpNumIsNeqq(__EGPa__,__EGPb__)
+/* return 1 if |a| <= error */
+#define EGlpNumIsNeqZero(__EGPa__,__EGPerr__)
+/* return 1 if a!= 0 */
+#define EGlpNumIsNeqqZero(__EGPa__)
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a EGlpNum_t the first number.
+ * @param b EGlpNum_t the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a < b, zero
+ * otherwise.
+ * */
+#define EGlpNumIsLess(__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief test if a numer is greater than zero
+ * @param a number to test
+ * @return int one if success, zero otherwise.
+ * */
+#define EGlpNumIsGreatZero(__EGPa__)
+
+/* ========================================================================= */
+/** @brief test if a numer is less than zero
+ * @param a number to test
+ * @return int one if success, zero otherwise.
+ * */
+#define EGlpNumIsLessZero(__EGPa__)
+/* ========================================================================= */
+/** @brief test if the sum of the first two numbers is less thatn the third
+ * number.
+ * @param a EGlpNum_t the first number.
+ * @param b EGlpNum_t the second number
+ * @param c EGlpNum_t the third number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given a,__EGPb__, and c, return nonzero if (a + b < c), zero toherwise.
+ * */
+#define EGlpNumIsSumLess(__EGPa__,__EGPb__,__EGPc__)
+/* ========================================================================= */
+/** @brief test if the diference of the first two numbers is less thatn the
+ * third number.
+ * @param a EGlpNum_t the first number.
+ * @param b EGlpNum_t the second number
+ * @param c EGlpNum_t the third number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given a,__EGPb__, and c, return nonzero if (a - b < c), zero toherwise.
+ * */
+#define EGlpNumIsDiffLess(__EGPa__,__EGPb__,__EGPc__)
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a EGlpNum_t the first number.
+ * @param b int the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a < b, zero
+ * otherwise.
+ * */
+#define EGlpNumIsLessDbl(__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a EGlpNum_t the first number.
+ * @param b int the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a > b, zero
+ * otherwise.
+ * */
+#define EGlpNumIsGreaDbl(__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a EGlpNum_t the first number.
+ * @param b EGlpNum_t the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a <= b, zero
+ * otherwise.
+ * */
+#define EGlpNumIsLeq(__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief copy the value of the second number to the first.
+ * @param a EGlpNum_t source number (it won't change value).
+ * @param b EGlpNum_t source number (it won't change value).
+ * @param __EGden__ EGlpNum_t denominator of the difference (it won't change value).
+ * @param __EGdest__ EGlpNum_t where to store the value .
+ * @par Description:
+ * Set __EGdest__ = (a - b) / __EGden__ */
+#define EGlpNumCopyDiffRatio(__EGdest__,__EGPa__,__EGPb__,__EGden__)
+/* ========================================================================= */
+/** @brief copy the value of the second number to the first.
+ * @param a EGlpNum_t source number (it won't change value).
+ * @param b EGlpNum_t source number (it won't change value).
+ * @param __EGdest__ EGlpNum_t where to store the value stored in '__EGorig__'.
+ * @par Description:
+ * Set __EGdest__ = a - b */
+#define EGlpNumCopyDiff(__EGdest__,__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief copy the value of the sum of the second and third parameter
+ * @param a EGlpNum_t source number (it won't change value).
+ * @param b EGlpNum_t source number (it won't change value).
+ * @param __EGdest__ EGlpNum_t where to store the sum.
+ * @par Description:
+ * Set __EGdest__ = a + b */
+#define EGlpNumCopySum(__EGdest__,__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief copy the value of the second number to the first.
+ * @param __EGorig__ EGlpNum_t source number (it won't change value).
+ * @param __EGdest__ EGlpNum_t where to store the value stored in '__EGorig__'.
+ * @par Description:
+ * Given two numbers copy the values in '__EGorig__', into '__EGdest__'.
+ * */
+#define EGlpNumCopy(__EGdest__,__EGorig__)
+/* ========================================================================= */
+/** @brief change the fist number to the maximum between itself and the
+ * absolute value of the second.
+ * @param __EGorig__ EGlpNum_t source number (it won't change value).
+ * @param __EGdest__ EGlpNum_t where to store the value stored in '__EGorig__'.
+ * @par Description:
+ * implement __EGdest__ = max(__EGdest__,abs(__EGorig__))
+ * */
+#define EGlpNumSetToMaxAbs(__EGdest__,__EGorig__)
+#define EGlpNumSetToMinAbs(__EGdest__,__EGorig__)
+/* ========================================================================= */
+/** @brief copy the square of the second argument, divided by the third
+ * argument into the first argument.
+ * @param __EGdest__ EGlpNum_t where to store the result
+ * @param __EGorig__ EGlpNum_t second parameter
+ * @param __EGden__ EGlpNum_t third parameter
+ * @par Description:
+ * compute __EGdest__ = (__EGorig__*__EGorig__)/__EGden__
+ * */
+#define EGlpNumCopySqrOver(__EGdest__,__EGorig__,__EGden__)
+/* ========================================================================= */
+/** @brief copy the value of the absolute value of the second parameter to the
+ * first parameter.
+ * @param __EGorig__ EGlpNum_t source number (it won't change value).
+ * @param __EGdest__ EGlpNum_t where to store the absolute value stored
+ * in '__EGorig__'.
+ * @par Description:
+ * Given a number '__EGorig__', copy its absolute value to '__EGdest__'. i.e.
+ * __EGdest__ = |__EGorig__|
+ * */
+#define EGlpNumCopyAbs(__EGdest__,__EGorig__)
+/* ========================================================================= */
+/** @brief copy minus the value of the second parameter to the
+ * first parameter.
+ * @param __EGorig__ EGlpNum_t the source number (it won't change value).
+ * @param __EGdest__ EGlpNum_t where to store minus the value stored
+ * in '__EGorig__'.
+ * @par Description:
+ * Given a number '__EGorig__', copy minus the value to '__EGdest__'. i.e.
+ * __EGdest__ = -__EGorig__
+ * */
+#define EGlpNumCopyNeg(__EGdest__,__EGorig__)
+/* ========================================================================= */
+/** @brief Set des = __EGPa__/__EGPb__.
+ * @param __EGdest__ EGlpNum_t where we will store the result.
+ * @param __EGPa__ EGlpNum_t numerator of the fraction (possibly non an integer)
+ * @param __EGPb__ EGlpNum_t denominator of the fraction (possibly non an integer)
+ * @par Description:
+ * Set __EGdest__ = __EGPa__/__EGPb__
+ * */
+#define EGlpNumCopyFrac(__EGdest__,__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief copy the first 'size' values in the second array to the first array.
+ * @param __EGorig__ EGlpNum_t* pointer to the array from where we will copy the
+ * values (it won't change value).
+ * @param __EGdest__ EGlpNum_t* pointer to where to store the first 'size' values
+ * stored in '__EGorig__'.
+ * @param size unsigned int specifying how many values of '__EGorig__' will be copied
+ * onto '__EGdest__'
+ * @par Description:
+ * This function is provided to (possible) make fast copies of arrays of
+ * numbers, the arrays should be of length at least 'size', and the resulting
+ * copy is absolutely independent froom the original, any change in one vale of
+ * one array won't change values on the other array.
+ * */
+#define EGlpNumCopyArray(__EGdest__,__EGorig__,__EGPszb__)
+/* ========================================================================= */
+/** @brief Sub to a given number the product of two numbers.
+ * @param a EGlpNum_t the number that we are going to Sub to.
+ * @param b EGlpNum_t value to be multiplyed.
+ * @param c EGlpNum_t value to be multiplyed.
+ * @par Description:
+ * This function implements a = a - b*c, and clearly don't change the value
+ * stored in 'b' nor in 'c'.
+ * */
+#define EGlpNumSubInnProdTo(__EGPa__,__EGPb__,__EGPc__)
+/* ========================================================================= */
+/** @brief Add to a given number the product of two numbers.
+ * @param a EGlpNum_t the number that we are going to add to.
+ * @param b EGlpNum_t value to be multiplyed.
+ * @param c EGlpNum_t value to be multiplyed.
+ * @par Description:
+ * This function implements a = a + b*c, and clearly don't change the value
+ * stored in 'b' nor in 'c'.
+ * */
+#define EGlpNumAddInnProdTo(__EGPa__,__EGPb__,__EGPc__)
+/* ========================================================================= */
+/** @brief Substract to a given number the value of the second number.
+ * @param a EGlpNum_t the number that we are going to substract to.
+ * @param b unsigned int value to be substracted to 'a'.
+ * @par Description:
+ * This function implements a = a - b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define EGlpNumSubUiTo(__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief Add to a given number the value of the second number.
+ * @param a EGlpNum_t the number that we are going to add to.
+ * @param b unsigned int value to be added to 'a'.
+ * @par Description:
+ * This function implements a = a + b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define EGlpNumAddUiTo(__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief Add to a given number the value of the second number.
+ * @param a EGlpNum_t the number that we are going to add to.
+ * @param b EGlpNum_t value to be added to 'a'.
+ * @par Description:
+ * This function implements a = a + b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define EGlpNumAddTo(__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief Substract to a given number the value of the second number.
+ * @param a EGlpNum_t the number that we are going to substract
+ * from.
+ * @param b EGlpNum_t value to be substracted to 'a'.
+ * @par Description:
+ * This function implements a = a - b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define EGlpNumSubTo(__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief Multiply a given number by the value of the second number.
+ * @param a EGlpNum_t the number that we are going to multiply by
+ * the second number and store the result.
+ * @param b EGlpNum_t value to be multyply to 'a'.
+ * @par Description:
+ * This function implements a = a * b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define EGlpNumMultTo(__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief Divide a given number by the value of the second number.
+ * @param a EGlpNum_t the number that we are going to divide by
+ * the second number and store the result.
+ * @param b EGlpNum_t value to be divide to 'a'.
+ * @par Description:
+ * This function implements a = a / b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define EGlpNumDivTo(__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief Divide a given number by the value of the second number.
+ * @param a EGlpNum_t the number that we are going to divide by
+ * the second number and store the result.
+ * @param b unsigned int value to be divided to 'a'.
+ * @par Description:
+ * This function implements a = a / b, and don't change the value
+ * stored in 'b'.
+ * */
+#define EGlpNumDivUiTo(__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief Multiply a given number by the value of the second number.
+ * @param a EGlpNum_t the number that we are going to multiply by
+ * the second number and store the result.
+ * @param b unsigned int value to be multyply to 'a'.
+ * @par Description:
+ * This function implements a = a * b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define EGlpNumMultUiTo(__EGPa__,__EGPb__)
+/* ========================================================================= */
+/** @brief Reset the value of the pointed number to zero.
+ * @param a EGlpNum_t the value to be set to zero.
+ * @par Descrpition:
+ * Reset a to zero, i.e. implements a = 0;
+ * */
+#define EGlpNumZero(__EGPa__)
+/* ========================================================================= */
+/** @brief Reset the value of the pointed number to one.
+ * @param a EGlpNum_t value to be set to one.
+ * @par Descrpition:
+ * Reset a to zero, i.e. implements a = 1;
+ * */
+#define EGlpNumOne(__EGPa__)
+/* ========================================================================= */
+/** @brief Change the sign of the number.
+ * @param a EGlpNum_t number we will change sign.
+ * @par Descrpition:
+ * Change the sign of the given number, i.e. implements a = -a
+ * */
+#define EGlpNumSign(__EGPa__)
+/* ========================================================================= */
+/** @brief return the closest double value of the given pointer number.
+ * @param a EGlpNum_t number that we will be transformed to int.
+ * @return int the closest int representation of the given number.
+ * par Description:
+ * return the int number closest in value to the value stored in a.
+ * */
+#define EGlpNumToLf(__EGPa__)
+/* ========================================================================= */
+/** @brief initialize the internal memory of a given variable and set its
+ * initial value to zero */
+#define EGlpNumInitVar(__EGPa__)
+
+/* ========================================================================= */
+/** @brief free the internal memory of a given variable */
+#define EGlpNumClearVar(__EGPa__)
+#endif
+ /** @} */
+/* ========================================================================= */
+/** @brief Sort (in increasing order) a sub-set of entries in an array using
+ * quicksort, by permutating the order of the elements in the subset rather
+ * than in the whole original array.
+ * @param sz length of the permutation array.
+ * @param perm array of indices of elements that we want to sort.
+ * @param elem array (of length at least max(perm[k]:k=0,...,sz-1)) containing
+ * the elements to be sorted.
+ * @note The array of elements is not changed by this function.
+ * @note This code is based in concorde's implementation of
+ * permutation-quick-sort.
+ * */
+void uint32_EGutilPermSort (const size_t sz,
+ int *const perm,
+ const uint32_t * const elem);
+
+/* ========================================================================= */
+/** @brief Sort (in decreasing order) a sub-set of entries in an array using
+ * quicksort, by permutating the order of the elements in the subset rather
+ * than in the whole original array.
+ * @param sz length of the permutation array.
+ * @param perm array of indices of elements that we want to sort.
+ * @param elem array (of length at least max(perm[k]:k=0,...,sz-1)) containing
+ * the elements to be sorted.
+ * @note The array of elements is not changed by this function.
+ * @note This code is based in concorde's implementation of
+ * permutation-quick-sort.
+ * */
+void uint32_EGutilPermSort2 (const size_t sz,
+ int*const perm,
+ const uint32_t*const elem);
+
+
+/* ========================================================================= */
+#endif
diff --git a/qsopt_ex/eg_lpnum.mpf.h b/qsopt_ex/eg_lpnum.mpf.h
new file mode 100644
index 0000000..640afde
--- /dev/null
+++ b/qsopt_ex/eg_lpnum.mpf.h
@@ -0,0 +1,628 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ *
+ * 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
+ * */
+#ifndef __EG_LPNUM_MPF__
+#define __EG_LPNUM_MPF__
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <gmp.h>
+
+#include "eg_lpnum.h"
+
+/** @file
+ * @ingroup EGlpNum */
+/** @addtogroup EGlpNum */
+/** @{ */
+/* ========================================================================= */
+/** @brief This is the smallest difference (with the current precision) that can
+ * be distinguished betwen 1.0 and it's clossest representable number, in some
+ * sense it is the absolute minimum epsilon for comparisons */
+extern mpf_t mpf_eps;
+
+/* ========================================================================= */
+/** extern definitions of constaants for different set-ups */
+extern const mpf_t __zeroLpNum_mpf__;
+extern const mpf_t __oneLpNum_mpf__;
+extern const mpf_t __MaxLpNum_mpf__;
+extern const mpf_t __MinLpNum_mpf__;
+#define mpf_zeroLpNum __zeroLpNum_mpf__
+#define mpf_oneLpNum __oneLpNum_mpf__
+#define mpf_epsLpNum mpf_eps
+#define mpf_MaxLpNum __MaxLpNum_mpf__
+#define mpf_MinLpNum __MinLpNum_mpf__
+
+/* ========================================================================= */
+/** @brief Given a double exp, compute \f$ e^{exp} \f$ and store it in the given
+ * mpf_t number.
+ * @param exp double exponent to be used.
+ * @param num mpf_t number where to store the result.
+ * */
+#define mpf_EGlpNumEpow(num,exp) ({\
+ unsigned int __i = 0;\
+ int __lsgn = (exp)<0 ? 1:0;\
+ mpf_t __ntmp,__res,__lexp,__err;\
+ mpf_init_set_d(__lexp,exp);\
+ if(__lsgn) mpf_neg(__lexp,__lexp);\
+ mpf_init_set_ui(__ntmp,(unsigned long int)1);\
+ mpf_init_set_ui(__res,(unsigned long int)1);\
+ mpf_init(__err);\
+ mpf_div(__err,__ntmp,__res);\
+ while(mpf_cmp(__err,mpf_eps)>0)\
+ {\
+ mpf_mul(__ntmp,__ntmp,__lexp);\
+ mpf_div_ui(__ntmp,__ntmp,(unsigned long int)(++__i));\
+ mpf_add(__res,__res,__ntmp);\
+ mpf_div(__err,__ntmp,__res);\
+ }\
+ if(__lsgn) mpf_ui_div(num,(unsigned long int)1,__res);\
+ else mpf_set(num,__res);\
+ mpf_clear(__ntmp);\
+ mpf_clear(__res);\
+ mpf_clear(__err);\
+ mpf_clear(__lexp);})
+
+/* ========================================================================= */
+/** @brief Read from a string a number and store it in the given mpf_t,
+ * @return the number of chars readed from the input string */
+#define mpf_EGlpNumReadStr(a,str) ({\
+ int __i =0;\
+ char __lpstr__[4096];\
+ mp_exp_t __lexp;\
+ mpf_set_str(a,str,10);\
+ mpf_get_str(__lpstr__,&__lexp,10,(size_t)0,a);\
+ __i = strlen(__lpstr__);\
+ __i;})
+
+/* ========================================================================= */
+/** @brief given a mpf_t, write it to a string (to be allocated internally),
+ * and return it. */
+#define mpf_EGlpNumGetStr(a) ({\
+ char *__out= 0;\
+ mp_exp_t __lexp = 0;\
+ size_t __pos = 0,__lo = (mpf_cmp_ui(a,(unsigned long)0) < 0) ? 1:0;\
+ char __lpstr__[4096];\
+ mpf_get_str(__lpstr__,&__lexp,10,(size_t)25,a);\
+ __pos = strlen(__lpstr__) + ((size_t)(__lo + 2));\
+ __out = EGsMalloc(char,__pos+((size_t)15));\
+ if(__lo) sprintf(__out,"-0.");\
+ else sprintf(__out,"0.");\
+ sprintf(__out+__lo+2,"%s",__lpstr__+__lo);\
+ if(__pos == 2) __out[1] = '\0';\
+ else if(__lexp != 0)\
+ {\
+ __out[__pos-__lo] = 'e';\
+ snprintf(__out+__pos+1-__lo,(size_t)(12-__lo),"%d",(int)__lexp);\
+ }\
+ __out;})
+
+/* ========================================================================= */
+/** @brief given an array of type mpf_t, free it, if the pointer is NULL
+ * nothing happen. */
+#define mpf_EGlpNumFreeArray(ea) ({\
+ size_t __sz = __EGlpNumArraySize(ea);\
+ mpf_t* __ptr__ = (ea);\
+ while(__sz--) mpf_clear(__ptr__[__sz]);\
+ __EGlpNumFreeArray(ea);})
+
+
+/* ========================================================================= */
+/** @brief Reallocate and initialize (if needed) 'size' elements of type
+ * mpf_t and return it, if no more memory, exit(1) */
+#define mpf_EGlpNumReallocArray(lptr, lsize) ({ \
+ mpf_t** __ptr__ = (lptr); \
+ size_t __sz__ = (lsize); \
+ size_t *__ntmp__ = (size_t *) *__ptr__; \
+ size_t __psz__; \
+ /* if no memory allocated before we just call the regular allocator */ \
+ if (!*__ptr__) *__ptr__ = mpf_EGlpNumAllocArray (__sz__); \
+ else \
+ { \
+ /* first check that the previous size is not larger than the current */ \
+ __ntmp__--; \
+ __psz__ = __ntmp__[0]; \
+ if (__psz__ < __sz__) \
+ { \
+ /* now we have to do the reallocation */ \
+ *__ptr__ = (mpf_t *) __ntmp__; \
+ *__ptr__ = EGrealloc(*__ptr__, sizeof(mpf_t) * __sz__ +sizeof(size_t));\
+ __ntmp__ = (size_t *) *__ptr__; \
+ __ntmp__[0] = __sz__; \
+ __ntmp__++; \
+ *__ptr__ = (mpf_t *) __ntmp__; \
+ for (; __psz__ < __sz__; __psz__++) mpf_init ((*__ptr__)[__psz__]); \
+ } \
+ } \
+})
+
+/* ========================================================================= */
+/** @brief Allocate and initialize (if needed) 'size' elements of type mpf_t
+ * and return it, if no more memory, exit(1) */
+#define mpf_EGlpNumAllocArray(size) ({\
+ size_t __i__ = (size);\
+ mpf_t *__res = __EGlpNumAllocArray(mpf_t,__i__);\
+ while(__i__--) mpf_init(__res[__i__]);\
+ __res;})
+
+/* ========================================================================= */
+/** @brief set the given number pointer, set its value to the given double.
+ * @param var mpf_t where we will store the double value.
+ * @param dbl double value to be stored in 'var'.
+ * @par Description:
+ * This function is intended to set initial values to variables; note that the
+ * double is a number and not a pointer to that value, be carefull with this
+ * detail. Also, due to implementation details this function can't deal with
+ * numbers above 1e158 or smaller than 1e-158. Note also that if the number is
+ * writen in the form \f$x=\bar{x}\cdot 2^e\f$ with \f$0.5<|\bar{x}|<1\f$,
+ * then \f$\left|x-\frac{p}{q}\right|<2^{e-64}\f$.
+ * */
+#define mpf_EGlpNumSet(var, dbl) mpf_set_d(var,(double)(dbl))
+
+/* ========================================================================= */
+/** @brief Stores in the first number the ceil value of the second number, i.e.
+ * EGlpNumCeil(a,b) <==> a= ceil(b) */
+#define mpf_EGlpNumCeil(a, b) mpf_ceil(a,b)
+
+/* ========================================================================= */
+/** @brief Stores in the first number the floor value of the second number, i.e.
+ * EGlpNumFloor(a,b) <==> a= floor(b) */
+#define mpf_EGlpNumFloor(a, b) mpf_floor(a,b)
+
+/* ========================================================================= */
+/** @brief store the (multiplicative) inverse of a number to itself, i.e.
+ * implement a = 1/a.
+ * @param a the number to be inverted. */
+#define mpf_EGlpNumInv(a) mpf_ui_div(a,(unsigned long int)1,a)
+
+/* ========================================================================= */
+/** @brief Compare if two numbers are equal within a maximum __error.
+ * @param a mpf_t first number to compare.
+ * @param b mpf_t second number to compare.
+ * @return int one in success, zero oterwise.
+ * @par Description:
+ * Given two numbers 'a','b' return 1 if a == b, otherwise it return 0
+ * */
+#define mpf_EGlpNumIsEqqual(a,b) (mpf_cmp(a,b) == 0)
+
+/* ========================================================================= */
+/** @brief Compare if two numbers are equal within a maximum __error.
+ * @param a mpf_t first number to compare.
+ * @param b mpf_t second number to compare.
+ * @param __error mpf_t maximum difference allowed between both
+ * numbers.
+ * @return int one in success, zero oterwise.
+ * @par Description:
+ * Given two numbers 'a','b' and a tolerance '__error',
+ * return 1 if |a-b|<= __error, otherwise it return 0.
+ * */
+#define mpf_EGlpNumIsEqual(a,b,__error) ({\
+ mpf_t __lpnum__;int __res__=0;mpf_init(__lpnum__);\
+ mpf_sub (__lpnum__, a, b);\
+ mpf_abs (__lpnum__, __lpnum__);\
+ __res__=(mpf_cmp (__lpnum__, __error) <= 0);\
+ mpf_clear(__lpnum__);\
+ __res__;\
+})
+
+#define mpf_EGlpNumIsNeq(a,b,__error) ({\
+ mpf_t __lpnum__;int __res__=0;mpf_init(__lpnum__);\
+ mpf_sub (__lpnum__, a, b);\
+ mpf_abs (__lpnum__, __lpnum__);\
+ __res__=(mpf_cmp (__lpnum__, __error) > 0);\
+ mpf_clear(__lpnum__);\
+ __res__;\
+})
+
+#define mpf_EGlpNumIsNeqZero(a,__error) ({\
+ mpf_t __lpnum__;int __res__=0;mpf_init(__lpnum__);\
+ mpf_abs (__lpnum__, a);\
+ __res__=(mpf_cmp (__lpnum__, __error) > 0);\
+ mpf_clear(__lpnum__);\
+ __res__;\
+})
+
+#define mpf_EGlpNumIsNeqqZero(a) (mpf_sgn(a))
+#define mpf_EGlpNumIsNeqq(a,b) (mpf_cmp(a,b)!=0)
+
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a mpf_t the first number.
+ * @param b mpf_t the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a < b, zero
+ * otherwise.
+ * */
+#define mpf_EGlpNumIsLess(a,b) (mpf_cmp(a,b) < 0)
+
+/* ========================================================================= */
+/** @brief test if a given number is greater than zero
+ * @param a number to test
+ * @return int one if success, zero otherwise.
+ * */
+#define mpf_EGlpNumIsGreatZero(a) (mpf_sgn(a) > 0)
+
+/* ========================================================================= */
+/** @brief test if a given number is less than zero
+ * @param a number to test
+ * @return int one if success, zero otherwise.
+ * */
+#define mpf_EGlpNumIsLessZero(a) (mpf_sgn(a) < 0)
+
+/* ========================================================================= */
+/** @brief test if the sum of the first two numbers is less thatn the third
+ * number.
+ * @param a mpf_t the first number.
+ * @param b mpf_t the second number
+ * @param c mpf_t the third number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given a,b, and c, return nonzero if (a + b < c), zero toherwise.
+ * */
+#define mpf_EGlpNumIsSumLess(a, b, c) ({\
+ mpf_t __lpnum__;int __res__=0;mpf_init(__lpnum__);\
+ mpf_add (__lpnum__, a, b);\
+ __res__=(mpf_cmp (__lpnum__, c) < 0);\
+ mpf_clear(__lpnum__);\
+ __res__;\
+})
+
+/* ========================================================================= */
+/** @brief test if the diference of the first two numbers is less thatn the
+ * third number.
+ * @param a mpf_t the first number.
+ * @param b mpf_t the second number
+ * @param c mpf_t the third number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given a,b, and c, return nonzero if (a - b < c), zero toherwise.
+ * */
+#define mpf_EGlpNumIsDiffLess(a, b, c) ({\
+ mpf_t __lpnum__;int __res__=0;mpf_init(__lpnum__);\
+ mpf_sub (__lpnum__, a, b);\
+ __res__=(mpf_cmp (__lpnum__, c) < 0);\
+ mpf_clear(__lpnum__);\
+ __res__;\
+})
+
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a mpf_t the first number.
+ * @param b double the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a < b, zero
+ * otherwise.
+ * */
+#define mpf_EGlpNumIsLessDbl(a,b) (mpf_cmp_d(a,((double)(b))) < 0)
+
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a mpf_t the first number.
+ * @param b double the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a > b, zero
+ * otherwise.
+ * */
+#define mpf_EGlpNumIsGreaDbl(a,b) (mpf_cmp_d(a,((double)(b))) > 0)
+
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a mpf_t the first number.
+ * @param b mpf_t the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a <= b, zero
+ * otherwise.
+ * */
+#define mpf_EGlpNumIsLeq(a,b) (mpf_cmp(a,b) <= 0)
+
+/* ========================================================================= */
+/** @brief copy the value of the second number to the first.
+ * @param a mpf_t source number (it won't change value).
+ * @param b mpf_t source number (it won't change value).
+ * @param c mpf_t denominator of the difference (it won't change value).
+ * @param d mpf_t where to store the value .
+ * @par Description:
+ * Set @f$a = \frac{b - c}{d} @f$ */
+#define mpf_EGlpNumCopyDiffRatio(a, b, c, d) ({\
+ mpf_sub (a, b, c);\
+ mpf_div (a, a, d);\
+})
+
+/* ========================================================================= */
+/** @brief copy the value of the second number to the first.
+ * @param a mpf_t source number (it won't change value).
+ * @param b mpf_t source number (it won't change value).
+ * @param dest mpf_t where to store the value stored in 'orig'.
+ * @par Description:
+ * Set dest = a - b */
+#define mpf_EGlpNumCopyDiff(dest,a,b) mpf_sub(dest,a,b)
+
+/* ========================================================================= */
+/** @brief copy the value of the sum of the second and third parameter
+ * @param a mpf_t source number (it won't change value).
+ * @param b mpf_t source number (it won't change value).
+ * @param dest mpf_t where to store the sum.
+ * @par Description:
+ * Set dest = a + b */
+#define mpf_EGlpNumCopySum(dest,a,b) mpf_add(dest,a,b)
+
+/* ========================================================================= */
+/** @brief copy the value of the second number to the first.
+ * @param orig mpf_t source number (it won't change value).
+ * @param dest mpf_t where to store the value stored in 'orig'.
+ * @par Description:
+ * Given two numbers copy the values in 'orig', into 'dest'.
+ * */
+#define mpf_EGlpNumCopy(dest,orig) mpf_set(dest,orig)
+
+/* ========================================================================= */
+/** @brief change the fist number to the maximum between itself and the
+ * absolute value of the second.
+ * @param orig mpf_t source number (it won't change value).
+ * @param dest mpf_t where to store the value stored in 'orig'.
+ * @par Description:
+ * implement dest = max(dest,abs(orig))
+ * */
+#define mpf_EGlpNumSetToMaxAbs(dest, orig) ({\
+ mpf_t __lpnum__;mpf_init(__lpnum__);\
+ mpf_abs (__lpnum__, orig);\
+ if (mpf_cmp (dest, __lpnum__) < 0) mpf_set (dest, __lpnum__);\
+ mpf_clear(__lpnum__);})
+
+#define mpf_EGlpNumSetToMinAbs(dest, orig) ({\
+ mpf_t __lpnum__;mpf_init(__lpnum__);\
+ mpf_abs (__lpnum__, orig);\
+ if (mpf_cmp (dest, __lpnum__) > 0) mpf_set (dest, __lpnum__);\
+ mpf_clear(__lpnum__);})
+
+/* ========================================================================= */
+/** @brief copy the square of the second argument, divided by the third
+ * argument into the first argument.
+ * @param dest mpf_t where to store the result
+ * @param orig mpf_t second parameter
+ * @param den mpf_t third parameter
+ * @par Description:
+ * compute dest = (orig*orig)/den
+ * */
+#define mpf_EGlpNumCopySqrOver(dest, orig, den) ({\
+ mpf_mul (dest, orig, orig);\
+ mpf_div (dest, dest, den);\
+})
+
+/* ========================================================================= */
+/** @brief copy the value of the absolute value of the second parameter to the
+ * first parameter.
+ * @param orig mpf_t source number (it won't change value).
+ * @param dest mpf_t where to store the absolute value stored
+ * in 'orig'.
+ * @par Description:
+ * Given a number 'orig', copy its absolute value to 'dest'. i.e.
+ * dest = |orig|
+ * */
+#define mpf_EGlpNumCopyAbs(dest,orig) mpf_abs(dest,orig)
+
+/* ========================================================================= */
+/** @brief copy minus the value of the second parameter to the
+ * first parameter.
+ * @param orig mpf_t the source number (it won't change value).
+ * @param dest mpf_t where to store minus the value stored
+ * in 'orig'.
+ * @par Description:
+ * Given a number 'orig', copy minus the value to 'dest'. i.e.
+ * dest = -orig
+ * */
+#define mpf_EGlpNumCopyNeg(dest,orig) mpf_neg(dest,orig)
+
+/* ========================================================================= */
+/** @brief Set des = op1/op2.
+ * @param dest mpf_t where we will store the result.
+ * @param op1 mpf_t numerator of the fraction (possibly non an integer)
+ * @param op2 mpf_t denominator of the fraction (possibly non an integer)
+ * @par Description:
+ * Set des = op1/op2
+ * */
+#define mpf_EGlpNumCopyFrac(dest,op1,op2) mpf_div(dest,op1,op2)
+
+/* ========================================================================= */
+/** @brief copy the first 'size' values in the second array to the first array.
+ * @param orig mpf_t* pointer to the array from where we will copy the
+ * values (it won't change value).
+ * @param dest mpf_t* pointer to where to store the first 'size' values
+ * stored in 'orig'.
+ * @param size unsigned int specifying how many values of 'orig' will be copied
+ * onto 'dest'
+ * @par Description:
+ * This function is provided to (possible) make fast copies of arrays of
+ * numbers, the arrays should be of length at least 'size', and the resulting
+ * copy is absolutely independent froom the original, any change in one vale of
+ * one array won't change values on the other array.
+ * */
+#define mpf_EGlpNumCopyArray(dest,orig,size) {\
+ register unsigned int __i__ = (size);\
+ for(;__i__--;)\
+ {\
+ mpf_set(dest[__i__],orig[__i__]);\
+ }\
+}
+
+/* ========================================================================= */
+/** @brief Sub to a given number the product of two numbers.
+ * @param a mpf_t the number that we are going to Sub to.
+ * @param b mpf_t value to be multiplyed.
+ * @param c mpf_t value to be multiplyed.
+ * @par Description:
+ * This function implements a = a - b*c, and clearly don't change the value
+ * stored in 'b' nor in 'c'.
+ * */
+#define mpf_EGlpNumSubInnProdTo(a, b, c) ({\
+ mpf_t __lpnum__;mpf_init(__lpnum__);\
+ mpf_mul (__lpnum__, b, c);\
+ mpf_sub (a, a, __lpnum__);\
+ mpf_clear(__lpnum__);\
+})
+
+/* ========================================================================= */
+/** @brief Add to a given number the product of two numbers.
+ * @param a mpf_t the number that we are going to add to.
+ * @param b mpf_t value to be multiplyed.
+ * @param c mpf_t value to be multiplyed.
+ * @par Description:
+ * This function implements a = a + b*c, and clearly don't change the value
+ * stored in 'b' nor in 'c'.
+ * */
+#define mpf_EGlpNumAddInnProdTo(a, b, c) ({\
+ mpf_t __lpnum__;mpf_init(__lpnum__);\
+ mpf_mul (__lpnum__, b, c);\
+ mpf_add (a, a, __lpnum__);\
+ mpf_clear(__lpnum__);\
+})
+
+/* ========================================================================= */
+/** @brief Substract to a given number the value of the second number.
+ * @param a mpf_t the number that we are going to substract to.
+ * @param b unsigned int value to be substracted to 'a'.
+ * @par Description:
+ * This function implements a = a - b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define mpf_EGlpNumSubUiTo(a,b) mpf_sub_ui(a,a,((unsigned long)(b)))
+
+/* ========================================================================= */
+/** @brief Add to a given number the value of the second number.
+ * @param a mpf_t the number that we are going to add to.
+ * @param b unsigned int value to be added to 'a'.
+ * @par Description:
+ * This function implements a = a + b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define mpf_EGlpNumAddUiTo(a,b) mpf_add_ui(a,a,((unsigned long)(b)))
+
+/* ========================================================================= */
+/** @brief Add to a given number the value of the second number.
+ * @param a mpf_t the number that we are going to add to.
+ * @param b mpf_t value to be added to 'a'.
+ * @par Description:
+ * This function implements a = a + b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define mpf_EGlpNumAddTo(a,b) mpf_add(a,a,b)
+
+/* ========================================================================= */
+/** @brief Substract to a given number the value of the second number.
+ * @param a mpf_t the number that we are going to substract
+ * from.
+ * @param b mpf_t value to be substracted to 'a'.
+ * @par Description:
+ * This function implements a = a - b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define mpf_EGlpNumSubTo(a,b) mpf_sub(a,a,b)
+
+/* ========================================================================= */
+/** @brief Multiply a given number by the value of the second number.
+ * @param a mpf_t the number that we are going to multiply by
+ * the second number and store the result.
+ * @param b mpf_t value to be multyply to 'a'.
+ * @par Description:
+ * This function implements a = a * b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define mpf_EGlpNumMultTo(a,b) mpf_mul(a,a,b)
+
+/* ========================================================================= */
+/** @brief Divide a given number by the value of the second number.
+ * @param a mpf_t the number that we are going to divide by
+ * the second number and store the result.
+ * @param b mpf_t value to be divide to 'a'.
+ * @par Description:
+ * This function implements a = a / b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define mpf_EGlpNumDivTo(a,b) mpf_div(a,a,b)
+
+/* ========================================================================= */
+/** @brief Divide a given number by the value of the second number.
+ * @param a mpf_t the number that we are going to divide by
+ * the second number and store the result.
+ * @param b unsigned int value to be divided to 'a'.
+ * @par Description:
+ * This function implements a = a / b, and don't change the value
+ * stored in 'b'.
+ * */
+#define mpf_EGlpNumDivUiTo(a,b) mpf_div_ui(a,a,((unsigned long)(b)))
+
+/* ========================================================================= */
+/** @brief Multiply a given number by the value of the second number.
+ * @param a mpf_t the number that we are going to multiply by
+ * the second number and store the result.
+ * @param b unsigned int value to be multyply to 'a'.
+ * @par Description:
+ * This function implements a = a * b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define mpf_EGlpNumMultUiTo(a,b) mpf_mul_ui(a,a,((unsigned long)(b)))
+
+/* ========================================================================= */
+/** @brief Reset the value of the pointed number to zero.
+ * @param a mpf_t the value to be set to zero.
+ * @par Descrpition:
+ * Reset a to zero, i.e. implements a = 0;
+ * */
+#define mpf_EGlpNumZero(a) mpf_set_ui(a,(unsigned long)0)
+
+/* ========================================================================= */
+/** @brief Reset the value of the pointed number to one.
+ * @param a mpf_t value to be set to one.
+ * @par Descrpition:
+ * Reset a to zero, i.e. implements a = 1;
+ * */
+#define mpf_EGlpNumOne(a) mpf_set_ui(a,(unsigned long)1)
+
+/* ========================================================================= */
+/** @brief Change the sign of the number.
+ * @param a mpf_t number we will change sign.
+ * @par Descrpition:
+ * Change the sign of the given number, i.e. implements a = -a
+ * */
+#define mpf_EGlpNumSign(a) mpf_neg(a,a)
+
+/* ========================================================================= */
+/** @brief return the closest double value of the given pointer number.
+ * @param a mpf_t number that we will be transformed to double.
+ * @return double the closest double representation of the given number.
+ * par Description:
+ * return the double number closest in value to the value stored in a.
+ * */
+#define mpf_EGlpNumToLf(a) mpf_get_d(a)
+
+/* ========================================================================= */
+/** @brief initialize the internal memory of a given variable */
+#define mpf_EGlpNumInitVar(a) mpf_init(a)
+
+/* ========================================================================= */
+/** @brief free the internal memory of a given variable */
+#define mpf_EGlpNumClearVar(a) mpf_clear(a)
+
+/* ========================================================================= */
+/** @} */
+#endif
diff --git a/qsopt_ex/eg_lpnum.mpq.h b/qsopt_ex/eg_lpnum.mpq.h
new file mode 100644
index 0000000..e04c83b
--- /dev/null
+++ b/qsopt_ex/eg_lpnum.mpq.h
@@ -0,0 +1,596 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ *
+ * 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
+ * */
+#ifndef __EG_LPNUM_MPQ__
+#define __EG_LPNUM_MPQ__
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <gmp.h>
+
+#include "eg_lpnum.h"
+
+/** @file
+ * @brief Interface for rational implementation of the EGlpNum_t type.
+ * @par History
+ * - 2006-02-01
+ * - Add verbosity flag for continued fraction conversions.
+ * @ingroup EGlpNum */
+/** @addtogroup EGlpNum */
+/** @{ */
+/* ========================================================================= */
+/** extern definitions of constaants for different set-ups */
+extern const mpq_t __zeroLpNum_mpq__;
+extern const mpq_t __oneLpNum_mpq__;
+extern const mpq_t __MaxLpNum_mpq__;
+extern const mpq_t __MinLpNum_mpq__;
+#define mpq_zeroLpNum __zeroLpNum_mpq__
+#define mpq_oneLpNum __oneLpNum_mpq__
+#define mpq_epsLpNum __zeroLpNum_mpq__
+#define mpq_MaxLpNum __MaxLpNum_mpq__
+#define mpq_MinLpNum __MinLpNum_mpq__
+
+/* ========================================================================= */
+/** @brief This function read a number in float form and store it in an mpq_t
+ * variable, returning how many chars read to create the number, the twist is
+ * that it does an 'exact' transformation, in the sense that 0.33333333 will be
+ * stored as 33333333/100000000.
+ * @param str input string.
+ * @param var variable where we will store the number as rational.
+ * @return number of reade chars.
+ * @par Descriptiom:
+ * If the input string doesn't contain a number, 'var' will be set to zero, and
+ * the number of readed chars will be zero, we assume that there are no leading
+ * empty spaces, (nor tabs), no eschape characters, and trailing zeros are
+ * considered as readed, but no the following spaces.
+ * @note
+ * This function will only read number in decimal base, in a future release we
+ * may include a more general reader. */
+int mpq_EGlpNumReadStrXc (mpq_t var,
+ char const *str);
+
+/* ========================================================================= */
+/** @brief Read from a string a number and store it in the given mpq_t, return
+ * the number of chars readed from the input string */
+#define mpq_EGlpNumReadStr(a,str) mpq_EGlpNumReadStrXc(a,str)
+
+/* ========================================================================= */
+/** @brief given a mpq_t, write it to a string (to be allocated internally),
+ * and return it. */
+#define mpq_EGlpNumGetStr(a) ({\
+ const size_t __sz = mpz_sizeinbase(mpq_numref(a),10) + mpz_sizeinbase(mpq_denref(a),10) + 3;\
+ char *__str=EGsMalloc(char,__sz);\
+ mpq_get_str(__str,10,a);})
+
+/* ========================================================================= */
+/** @brief given an array of type mpq_t, free it, if the pointer is NULL
+ * nothing happen. */
+#define mpq_EGlpNumFreeArray(ea) ({\
+ size_t __sz = __EGlpNumArraySize(ea);\
+ mpq_t* __ptr__ = (ea);\
+ while(__sz--) mpq_clear(__ptr__[__sz]);\
+ __EGlpNumFreeArray(ea);})
+
+
+/* ========================================================================= */
+/** @brief Reallocate and initialize (if needed) 'size' elements of type
+ * mpq_t and return it, if no more memory, exit(1) */
+#define mpq_EGlpNumReallocArray(lptr, lsize) ({\
+ mpq_t **__ptr__ = (lptr);\
+ size_t *__ntmp__ = (size_t *) *__ptr__, __sz__ = (lsize);\
+ size_t __psz__;\
+ /* if no memory allocated before we just call the regular allocator */\
+ if (!*__ptr__)\
+ *__ptr__ = mpq_EGlpNumAllocArray (__sz__);\
+ else\
+ {\
+ /* first check that the previous size is not larger than the current */\
+ __ntmp__--;\
+ __psz__ = __ntmp__[0];\
+ if (__psz__ < __sz__)\
+ {\
+ /* now we have to do the reallocation */\
+ *__ptr__ = (mpq_t *) __ntmp__;\
+ *__ptr__ = EGrealloc(*__ptr__,sizeof(mpq_t) * __sz__ + sizeof(size_t));\
+ __ntmp__ = (size_t *) *__ptr__;\
+ __ntmp__[0] = __sz__;\
+ __ntmp__++;\
+ *__ptr__ = (mpq_t *) __ntmp__;\
+ for (; __psz__ < __sz__; __psz__++) mpq_init ((*__ptr__)[__psz__]);\
+ }\
+ }\
+})
+
+/* ========================================================================= */
+/** @brief Allocate and initialize (if needed) 'size' elements of type mpq_t
+ * and return it, if no more memory, exit(1) */
+#define mpq_EGlpNumAllocArray(size) ({\
+ size_t __i__ = (size);\
+ mpq_t *__res = __EGlpNumAllocArray(mpq_t,__i__);\
+ while(__i__--) mpq_init(__res[__i__]);\
+ __res;})
+
+/* ========================================================================= */
+/** @brief set the given rational number , to the value to the value of the
+ * given mpf_t, this conversion is done using the continuous fraction method.
+ * @param var mpq_t where we will store the value.
+ * @param flt mpf_t value to be stored in 'var'.
+ * @par Description:
+ * This function is intended to set initial values to variables. Note also
+ * that if the number is
+ * writen in the form \f$x=\bar{x}\cdot 2^e\f$ with \f$0.5<|\bar{x}|<1\f$,
+ * then \f$\left|x-\frac{p}{q}\right|<2^{e-EGLPNUM_PRECISION}\f$.
+ * */
+void mpq_EGlpNumSet_mpf (mpq_t var,
+ mpf_t flt);
+
+/* ========================================================================= */
+/** @brief set the given number pointer, set its value to the given double.
+ * @param var mpq_t where we will store the double value.
+ * @param dbl double value to be stored in 'var'.
+ * @par Description:
+ * This function is intended to set initial values to variables; note that the
+ * double is a number and not a pointer to that value, be carefull with this
+ * detail. Also, due to implementation details this function can't deal with
+ * numbers above 1e158 or smaller than 1e-158. Note also that if the number is
+ * writen in the form \f$x=\bar{x}\cdot 2^e\f$ with \f$0.5<|\bar{x}|<1\f$,
+ * then \f$\left|x-\frac{p}{q}\right|<2^{e-64}\f$.
+ * */
+void mpq_EGlpNumSet (mpq_t var,
+ const double dbl);
+
+/* ========================================================================= */
+/** @brief Stores in the first number the ceil value of the second number, i.e.
+ * EGlpNumCeil(a,b) <==> a= ceil(b) */
+#define mpq_EGlpNumCeil(a, b) ({\
+ mpz_cdiv_q (mpq_numref (a), mpq_numref (b), mpq_denref (b));\
+ mpz_set_ui (mpq_denref (a), (unsigned long int)1);\
+})
+
+/* ========================================================================= */
+/** @brief Stores in the first number the floor value of the second number, i.e.
+ * EGlpNumFloor(a,b) <==> a= floor(b) */
+#define mpq_EGlpNumFloor(a, b) ({\
+ mpz_fdiv_q (mpq_numref (a), mpq_numref (b), mpq_denref (b));\
+ mpz_set_ui (mpq_denref (a), (unsigned long int)1);\
+})
+
+/* ========================================================================= */
+/** @brief store the (multiplicative) inverse of a number to itself, i.e.
+ * implement a = 1/a.
+ * @param a the number to be inverted. */
+#define mpq_EGlpNumInv(a) mpq_inv(a,a)
+
+/* ========================================================================= */
+/** @brief Compare if two numbers are equal within a maximum error.
+ * @param a mpq_t first number to compare.
+ * @param b mpq_t second number to compare.
+ * @return int one in success, zero oterwise.
+ * @par Description:
+ * Given two numbers 'a','b' return 1 if a == b, otherwise it return 0
+ * */
+#define mpq_EGlpNumIsEqqual(a,b) (mpq_equal(a,b))
+
+/* ========================================================================= */
+/** @brief Compare if two numbers are equal within a maximum error.
+ * @param a mpq_t first number to compare.
+ * @param b mpq_t second number to compare.
+ * @param error mpq_t maximum difference allowed between both
+ * numbers.
+ * @return int one in success, zero oterwise.
+ * @par Description:
+ * Given two numbers 'a','b' and a tolerance 'error',
+ * return 1 if |a-b|<= error, otherwise it return 0.
+ * */
+#define mpq_EGlpNumIsEqual(a,b,error) (mpq_equal(a,b))
+#define mpq_EGlpNumIsNeq(a,b,error) (!(mpq_equal(a,b)))
+#define mpq_EGlpNumIsNeqq(a,b) (!(mpq_equal(a,b)))
+#define mpq_EGlpNumIsNeqZero(a,error) (mpq_sgn(a))
+#define mpq_EGlpNumIsNeqqZero(a) (mpq_sgn(a))
+
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a mpq_t the first number.
+ * @param b mpq_t the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a < b, zero
+ * otherwise.
+ * */
+#define mpq_EGlpNumIsLess(a,b) (mpq_cmp(a,b) < 0)
+
+/* ========================================================================= */
+/** @brief test if a number is greater than zero
+ * @param a number to test
+ * @return int one if success, zero otherwise.
+ * */
+#define mpq_EGlpNumIsGreatZero(a) (mpq_sgn(a) > 0)
+
+/* ========================================================================= */
+/** @brief test if a number is less than zero
+ * @param a number to test
+ * @return int one if success, zero otherwise.
+ * */
+#define mpq_EGlpNumIsLessZero(a) (mpq_sgn(a) < 0)
+
+/* ========================================================================= */
+/** @brief test if the sum of the first two numbers is less thatn the third
+ * number.
+ * @param a mpq_t the first number.
+ * @param b mpq_t the second number
+ * @param c mpq_t the third number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given a,b, and c, return nonzero if (a + b < c), zero toherwise.
+ * */
+#define mpq_EGlpNumIsSumLess(a, b, c) ({\
+ mpq_t __lpnum__;int __res__=0;mpq_init(__lpnum__);\
+ mpq_add(__lpnum__,a,b);\
+ __res__=(mpq_cmp (__lpnum__, c) < 0);\
+ mpq_clear(__lpnum__);\
+ __res__;\
+})
+
+/* ========================================================================= */
+/** @brief test if the diference of the first two numbers is less thatn the
+ * third number.
+ * @param a mpq_t the first number.
+ * @param b mpq_t the second number
+ * @param c mpq_t the third number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given a,b, and c, return nonzero if (a - b < c), zero toherwise.
+ * */
+#define mpq_EGlpNumIsDiffLess(a, b, c) ({\
+ mpq_t __lpnum__;int __res__=0;mpq_init(__lpnum__);\
+ mpq_sub (__lpnum__, a, b);\
+ __res__=(mpq_cmp (__lpnum__, c) < 0);\
+ mpq_clear(__lpnum__);\
+ __res__;\
+})
+
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a mpq_t the first number.
+ * @param b double the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a < b, zero
+ * otherwise.
+ * */
+#define mpq_EGlpNumIsLessDbl(a,b) (mpq_get_d(a) < b)
+
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a mpq_t the first number.
+ * @param b double the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a > b, zero
+ * otherwise.
+ * */
+#define mpq_EGlpNumIsGreaDbl(a,b) (mpq_get_d(a) > b)
+
+/* ========================================================================= */
+/** @brief test if the first number is bigger to the second number
+ * @param a mpq_t the first number.
+ * @param b mpq_t the second number
+ * @return int one if success, zero otherwise.
+ * @par Description:
+ * Given two numbers 'a' and 'b', return one if a <= b, zero
+ * otherwise.
+ * */
+#define mpq_EGlpNumIsLeq(a,b) (mpq_cmp(a,b) <= 0)
+
+/* ========================================================================= */
+/** @brief copy the value of the second number to the first.
+ * @param a mpq_t source number (it won't change value).
+ * @param b mpq_t source number (it won't change value).
+ * @param c mpq_t denominator of the difference (it won't change value).
+ * @param d mpq_t where to store the value .
+ * @par Description:
+ * Set @f$a = \frac{b - c}{d} @f$ */
+#define mpq_EGlpNumCopyDiffRatio(a, b, c, d) ({\
+ mpq_sub (a, b, c);\
+ mpq_div (a, a, d);\
+})
+
+/* ========================================================================= */
+/** @brief copy the value of the second number to the first.
+ * @param a mpq_t source number (it won't change value).
+ * @param b mpq_t source number (it won't change value).
+ * @param dest mpq_t where to store the value stored in 'orig'.
+ * @par Description:
+ * Set dest = a - b */
+#define mpq_EGlpNumCopyDiff(dest,a,b) mpq_sub(dest,a,b)
+
+/* ========================================================================= */
+/** @brief copy the value of the sum of the second and third parameter
+ * @param a mpq_t source number (it won't change value).
+ * @param b mpq_t source number (it won't change value).
+ * @param dest mpq_t where to store the sum.
+ * @par Description:
+ * Set dest = a + b */
+#define mpq_EGlpNumCopySum(dest,a,b) mpq_add(dest,a,b)
+
+/* ========================================================================= */
+/** @brief copy the value of the second number to the first.
+ * @param orig mpq_t source number (it won't change value).
+ * @param dest mpq_t where to store the value stored in 'orig'.
+ * @par Description:
+ * Given two numbers copy the values in 'orig', into 'dest'.
+ * */
+#define mpq_EGlpNumCopy(dest,orig) mpq_set(dest,orig)
+
+/* ========================================================================= */
+/** @brief change the fist number to the maximum between itself and the
+ * absolute value of the second.
+ * @param orig mpq_t source number (it won't change value).
+ * @param dest mpq_t where to store the value stored in 'orig'.
+ * @par Description:
+ * implement dest = max(dest,abs(orig))
+ * */
+#define mpq_EGlpNumSetToMaxAbs(dest, orig) ({\
+ mpq_t __lpnum__;mpq_init(__lpnum__);\
+ mpq_abs (__lpnum__, orig);\
+ if (mpq_cmp (dest, __lpnum__) < 0)\
+ mpq_set (dest, __lpnum__);\
+ mpq_clear(__lpnum__);\
+})
+
+#define mpq_EGlpNumSetToMinAbs(dest, orig) ({\
+ mpq_t __lpnum__;mpq_init(__lpnum__);\
+ mpq_abs (__lpnum__, orig);\
+ if (mpq_cmp (dest, __lpnum__) > 0)\
+ mpq_set (dest, __lpnum__);\
+ mpq_clear(__lpnum__);\
+})
+
+/* ========================================================================= */
+/** @brief copy the square of the second argument, divided by the third
+ * argument into the first argument.
+ * @param dest mpq_t where to store the result
+ * @param orig mpq_t second parameter
+ * @param den mpq_t third parameter
+ * @par Description:
+ * compute dest = (orig*orig)/den
+ * */
+#define mpq_EGlpNumCopySqrOver(dest, orig, den) ({\
+ mpq_mul (dest, orig, orig);\
+ mpq_div (dest, dest, den);\
+})
+
+/* ========================================================================= */
+/** @brief copy the value of the absolute value of the second parameter to the
+ * first parameter.
+ * @param orig mpq_t source number (it won't change value).
+ * @param dest mpq_t where to store the absolute value stored
+ * in 'orig'.
+ * @par Description:
+ * Given a number 'orig', copy its absolute value to 'dest'. i.e.
+ * dest = |orig|
+ * */
+#define mpq_EGlpNumCopyAbs(dest,orig) mpq_abs(dest,orig)
+
+/* ========================================================================= */
+/** @brief copy minus the value of the second parameter to the
+ * first parameter.
+ * @param orig mpq_t the source number (it won't change value).
+ * @param dest mpq_t where to store minus the value stored
+ * in 'orig'.
+ * @par Description:
+ * Given a number 'orig', copy minus the value to 'dest'. i.e.
+ * dest = -orig
+ * */
+#define mpq_EGlpNumCopyNeg(dest,orig) mpq_neg(dest,orig)
+
+/* ========================================================================= */
+/** @brief Set des = op1/op2.
+ * @param dest mpq_t where we will store the result.
+ * @param op1 mpq_t numerator of the fraction (possibly non an integer)
+ * @param op2 mpq_t denominator of the fraction (possibly non an integer)
+ * @par Description:
+ * Set des = op1/op2
+ * */
+#define mpq_EGlpNumCopyFrac(dest,op1,op2) mpq_div(dest,op1,op2)
+
+/* ========================================================================= */
+/** @brief copy the first 'size' values in the second array to the first array.
+ * @param orig mpq_t* pointer to the array from where we will copy the
+ * values (it won't change value).
+ * @param dest mpq_t* pointer to where to store the first 'size' values
+ * stored in 'orig'.
+ * @param size unsigned int specifying how many values of 'orig' will be copied
+ * onto 'dest'
+ * @par Description:
+ * This function is provided to (possible) make fast copies of arrays of
+ * numbers, the arrays should be of length at least 'size', and the resulting
+ * copy is absolutely independent froom the original, any change in one vale of
+ * one array won't change values on the other array.
+ * */
+#define mpq_EGlpNumCopyArray(dest,orig,size) {\
+ register unsigned int __i__ = size;\
+ for(;__i__--;)\
+ {\
+ mpq_set(dest[__i__],orig[__i__]);\
+ }\
+}
+
+/* ========================================================================= */
+/** @brief Sub to a given number the product of two numbers.
+ * @param a mpq_t the number that we are going to Sub to.
+ * @param b mpq_t value to be multiplyed.
+ * @param c mpq_t value to be multiplyed.
+ * @par Description:
+ * This function implements a = a - b*c, and clearly don't change the value
+ * stored in 'b' nor in 'c'.
+ * */
+#define mpq_EGlpNumSubInnProdTo(a, b, c) ({\
+ mpq_t __lpnum__;mpq_init(__lpnum__);\
+ mpq_mul (__lpnum__, b, c);\
+ mpq_sub (a, a, __lpnum__);\
+ mpq_clear(__lpnum__);\
+})
+
+/* ========================================================================= */
+/** @brief Add to a given number the product of two numbers.
+ * @param a mpq_t the number that we are going to add to.
+ * @param b mpq_t value to be multiplyed.
+ * @param c mpq_t value to be multiplyed.
+ * @par Description:
+ * This function implements a = a + b*c, and clearly don't change the value
+ * stored in 'b' nor in 'c'.
+ * */
+#define mpq_EGlpNumAddInnProdTo(a, b, c) ({\
+ mpq_t __lpnum__;mpq_init(__lpnum__);\
+ mpq_mul (__lpnum__, b, c);\
+ mpq_add (a, a, __lpnum__);\
+ mpq_clear(__lpnum__);\
+})
+
+/* ========================================================================= */
+/** @brief Substract to a given number the value of the second number.
+ * @param a mpq_t the number that we are going to substract to.
+ * @param b unsigned int value to be substracted to 'a'.
+ * @par Description:
+ * This function implements a = a - b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define mpq_EGlpNumSubUiTo(a,b) mpz_submul_ui(mpq_numref(a),mpq_denref(a),(unsigned long int)b)
+
+/* ========================================================================= */
+/** @brief Add to a given number the value of the second number.
+ * @param a mpq_t the number that we are going to add to.
+ * @param b unsigned int value to be added to 'a'.
+ * @par Description:
+ * This function implements a = a + b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define mpq_EGlpNumAddUiTo(a,b) mpz_addmul_ui(mpq_numref(a),mpq_denref(a),(unsigned long int)b)
+
+/* ========================================================================= */
+/** @brief Add to a given number the value of the second number.
+ * @param a mpq_t the number that we are going to add to.
+ * @param b mpq_t value to be added to 'a'.
+ * @par Description:
+ * This function implements a = a + b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define mpq_EGlpNumAddTo(a,b) mpq_add(a,a,b)
+
+/* ========================================================================= */
+/** @brief Substract to a given number the value of the second number.
+ * @param a mpq_t the number that we are going to substract
+ * from.
+ * @param b mpq_t value to be substracted to 'a'.
+ * @par Description:
+ * This function implements a = a - b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define mpq_EGlpNumSubTo(a,b) mpq_sub(a,a,b)
+
+/* ========================================================================= */
+/** @brief Multiply a given number by the value of the second number.
+ * @param a mpq_t the number that we are going to multiply by
+ * the second number and store the result.
+ * @param b mpq_t value to be multyply to 'a'.
+ * @par Description:
+ * This function implements a = a * b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define mpq_EGlpNumMultTo(a,b) mpq_mul(a,a,b)
+
+/* ========================================================================= */
+/** @brief Divide a given number by the value of the second number.
+ * @param a mpq_t the number that we are going to divide by
+ * the second number and store the result.
+ * @param b mpq_t value to be divide to 'a'.
+ * @par Description:
+ * This function implements a = a / b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define mpq_EGlpNumDivTo(a,b) mpq_div(a,a,b)
+
+/* ========================================================================= */
+/** @brief Divide a given number by the value of the second number.
+ * @param a mpq_t the number that we are going to divide by
+ * the second number and store the result.
+ * @param b unsigned int value to be divided to 'a'.
+ * @par Description:
+ * This function implements a = a / b, and don't change the value
+ * stored in 'b'.
+ * */
+#define mpq_EGlpNumDivUiTo(a,b) do{mpz_mul_ui(mpq_denref(a),mpq_denref(a),(unsigned long)b);mpq_canonicalize(a);}while(0)
+
+/* ========================================================================= */
+/** @brief Multiply a given number by the value of the second number.
+ * @param a mpq_t the number that we are going to multiply by
+ * the second number and store the result.
+ * @param b unsigned int value to be multyply to 'a'.
+ * @par Description:
+ * This function implements a = a * b, and clearly don't change the value
+ * stored in 'b'.
+ * */
+#define mpq_EGlpNumMultUiTo(a,b) do{mpz_mul_ui(mpq_numref(a),mpq_numref(a),(unsigned long int)b);mpq_canonicalize(a);}while(0)
+
+/* ========================================================================= */
+/** @brief Reset the value of the pointed number to zero.
+ * @param a mpq_t the value to be set to zero.
+ * @par Descrpition:
+ * Reset a to zero, i.e. implements a = 0;
+ * */
+#define mpq_EGlpNumZero(a) mpq_set_ui(a,(unsigned long)0,(unsigned long)1)
+
+/* ========================================================================= */
+/** @brief Reset the value of the pointed number to one.
+ * @param a mpq_t value to be set to one.
+ * @par Descrpition:
+ * Reset a to zero, i.e. implements a = 1;
+ * */
+#define mpq_EGlpNumOne(a) mpq_set_ui(a,(unsigned long)1,(unsigned long)1)
+
+/* ========================================================================= */
+/** @brief Change the sign of the number.
+ * @param a mpq_t number we will change sign.
+ * @par Descrpition:
+ * Change the sign of the given number, i.e. implements a = -a
+ * */
+#define mpq_EGlpNumSign(a) mpq_neg(a,a)
+
+/* ========================================================================= */
+/** @brief return the closest double value of the given pointer number.
+ * @param a mpq_t number that we will be transformed to double.
+ * @return double the closest double representation of the given number.
+ * par Description:
+ * return the double number closest in value to the value stored in a.
+ * */
+#define mpq_EGlpNumToLf(a) mpq_get_d(a)
+
+/* ========================================================================= */
+/** @brief initialize the internal memory of a given variable */
+#define mpq_EGlpNumInitVar(a) mpq_init(a)
+
+/* ========================================================================= */
+/** @brief free the internal memory of a given variable */
+#define mpq_EGlpNumClearVar(a) mpq_clear(a)
+
+/* ========================================================================= */
+/** @} */
+#endif
diff --git a/qsopt_ex/eg_macros.c b/qsopt_ex/eg_macros.c
new file mode 100644
index 0000000..42140ef
--- /dev/null
+++ b/qsopt_ex/eg_macros.c
@@ -0,0 +1,148 @@
+/* ========================================================================= */
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ *
+ * 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
+ * */
+/* ========================================================================= */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <setjmp.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/utsname.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "eg_macros.h"
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+/** @file
+ * @brief implementation of some macros.
+ *
+ * @version 0.9.2
+ * @par History:
+ * -2006-09-28
+ * - First implementation
+ * -2007-12-06
+ * - Add versioning information in header
+ * @ingroup EGmacros */
+/** @addtogroup EGmacros */
+/** @{ */
+/* ========================================================================= */
+void EGlib_info(void)
+{
+ int rval;
+ struct utsname uts;
+ rval = uname(&uts);
+ if(rval)
+ {
+ QSlog("Can't get host info");
+ }
+ else
+ {
+ QSlog("Host: %s, %s %s %s", uts.nodename, uts.sysname, uts.release, uts.machine);
+ QSlog("Current process id: %d", (int)getpid());
+ }
+}
+/** @} */
+/* ========================================================================= */
+jmp_buf __EGljmp;
+/* ========================================================================= */
+void EGsighandler(int s)
+{
+ switch(s)
+ {
+ case SIGXCPU:
+ /* time is over */
+ QSlog("TIME_LIMIT_REACHED (ending now)");
+ longjmp(__EGljmp,s);
+ break;
+ case SIGINT:
+ case SIGTERM:
+ case SIGTSTP:
+ /* time is over */
+ QSlog("USER_INTERRUPT (ending now)");
+ longjmp(__EGljmp,s);
+ break;
+ case SIGSEGV:
+ /* Memory is over or segmentation fault */
+ QSlog("MEMORY_LIMIT_REACHED (ending now)");
+ longjmp(__EGljmp,s);
+ break;
+ case SIGABRT:
+ /* something is sending an abort code.... stop execution, report the
+ * signal, do destruction and report and end */
+ QSlog("SIGABRT received (ending now)");
+ longjmp(__EGljmp,s);
+ break;
+ default:
+ QSlog("Unkown signal %d", s);
+ QSlog("Ending with status %d", s);
+ exit(s);
+ }
+}
+/* ========================================================================= */
+void __EGsigSetSignal(void)
+{
+ signal(SIGXCPU,EGsighandler);
+ signal(SIGINT,EGsighandler);
+ signal(SIGSEGV,EGsighandler);
+ signal(SIGABRT,EGsighandler);
+}
+/* ========================================================================= */
+void EGsetLimits(double max_rtime, unsigned long memlimit)
+{
+ struct rlimit mlim;
+ WARNIF(getrlimit(RLIMIT_CPU,&mlim));
+ MESSAGE(0, "Cur rtime limit %ld, trying to set to %lg", mlim.rlim_cur, max_rtime);
+ if(max_rtime > mlim.rlim_max) max_rtime = (double)mlim.rlim_max;
+ mlim.rlim_cur = (rlim_t)max_rtime;
+ WARNIF(setrlimit(RLIMIT_CPU,&mlim));
+ MESSAGE(0, "New rtime limit %ld (%.3lg)", mlim.rlim_cur, max_rtime);
+ WARNIF(getrlimit(RLIMIT_DATA,&mlim));
+ MESSAGE(0, "Cur data limit %ld,%ld (soft,hard)", mlim.rlim_cur,
+ mlim.rlim_max);
+ mlim.rlim_cur = memlimit;
+ WARNIF( setrlimit(RLIMIT_DATA,&mlim));
+ WARNIF( getrlimit(RLIMIT_DATA,&mlim));
+ MESSAGE(0, "New data limit %ld,%ld (soft,hard)", mlim.rlim_cur,
+ mlim.rlim_max);
+ WARNIF( getrlimit(RLIMIT_AS,&mlim));
+ MESSAGE(0, "Cur address space limit %ld,%ld (soft,hard)",
+ mlim.rlim_cur, mlim.rlim_max);
+ mlim.rlim_cur = memlimit;
+ WARNIF( setrlimit(RLIMIT_AS,&mlim));
+ WARNIF( getrlimit(RLIMIT_AS,&mlim));
+ MESSAGE(0, "New address space limit %ld,%ld (soft,hard)",
+ mlim.rlim_cur, mlim.rlim_max);
+ mlim.rlim_cur = 0;
+ WARNIF( setrlimit(RLIMIT_CORE,&mlim));
+ WARNIF( getrlimit(RLIMIT_CORE,&mlim));
+ MESSAGE(0, "New core dump space limit %ld,%ld (soft,hard)",
+ mlim.rlim_cur, mlim.rlim_max);
+ return;
+}
+/* ========================================================================= */
+/* end of eg_macros.c */
diff --git a/qsopt_ex/eg_macros.h b/qsopt_ex/eg_macros.h
new file mode 100644
index 0000000..1866041
--- /dev/null
+++ b/qsopt_ex/eg_macros.h
@@ -0,0 +1,270 @@
+/* ========================================================================= */
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ *
+ * 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
+ * */
+/* ========================================================================= */
+/** @defgroup EGmacros General Macros
+ * global macros and types for EGlib
+ *
+ * @version 0.9.2
+ * @par History:
+ * - 2013-04-30
+ * - Add EGaGetCElem EGaGetElem EGaGetPos to get array-based pointers and
+ * positions
+ * - 2012-10-12
+ * - Add TESTGD that jumps automatically to CLEANUP
+ * - 2011-12-06
+ * - Add generic signal handler and necesary macros
+ * - 2011-05-16
+ * - Add WARNIF(xxx) to warn (on screen) non-zero return values
+ * - 2010-08-31
+ * - Add EGcallD(xxx) short hand to EGcall(rval,CLEANUP,xxx)
+ * - 2010-04-30
+ * - Add IFMESSAGE messaging macro
+ * - 2010-02-20
+ * - Add EGcall macro to resume tracing calls.
+ * - 2009-07-21
+ * - Change macro-variables to __name convention to avoid name
+ * clashes
+ * - 2008-08-29
+ * - Add EG_RETURN
+ * - 2008-07-24
+ * - Add TESTGL
+ * - 2007-12-07
+ * - Add FTESTG and FTEST, that always test the parameters
+ * regardless of the debug level
+ * - 2007-01-19
+ * - Delete EGosGetOffset
+ * - 2006-09-28
+ * - Add function that display basic process information, including
+ * version and date of compilation of EGlib
+ * - 2005-12-19
+ * - Add float128 support ussing SoftFloat.
+ * - 2005-10-28
+ * - Add some status definitions for algorithms.
+ * - 2005-06-14
+ * - Add strdup definition, just for cleanliness when compiling
+ * - 2005-05-23
+ * - Add EGcontainerOf
+ * - 2005-05-03
+ * - Add typeof definition;
+ * - 2004-07-14
+ * - Add GNU_MP_Z GNU_MP_F and GNU_MP_Q to the type definitions.
+ * - 2004-07-12
+ * - Add EGRAT_TYPE to the type definitions.
+ * - 2004-03-17
+ * - Add TESTG that if recives something that is nonzero print an
+ * user message and the go to the given location.
+ * - 2004-02-05
+ * - Add CHECKRVALG that checks a return value, display a mesage,
+ * and then perform a goto.
+ * - 2003-12-01
+ * - Add definition of a 'copy' function and its MP version.
+ * - 2003-11-20
+ * - Add PTRTEST that check if a pointer points to the first 64Kb of
+ * memory internal memory. Althought such situation may happend
+ * (if we work in kernel-related stuff), it is usually an error
+ * when we try to access such a memory.
+ * - 2003-09-08
+ * - Add ADVTESTL
+ * - 2003-07-10
+ * - Add MESSAGEF, ADVCHECKRVAL
+ * - 2003-07-02
+ * - Add EGosGetData, EGosSetData, EGosGetOffset
+ * - 2003-06-16
+ * - Add EXITL macro
+ * - 2003-06-06
+ * - Add TESTL macro to test conditions but only when the debug
+ * level is at least some value
+ * - 2003-05-22
+ * - Add EXITRVAL
+ * - 2003-05-15
+ * - Add CHECKRVAL MESSAGE and WARNING macros.
+ * - 2003-05-08
+ * - Add support for variadic macros for EXIT and TEST
+ * - Define EGRAND_MAX for SUN and LINUX acordingly, this is becouse
+ * for some reason the value of RAND_MAX in SUN is not as
+ * specified in stdlib.h but rather 1 << 31 - 1. Still I am not
+ * sure about the maximum value of rand() on sun... will fix that
+ * later on to.
+ * - Add a mesage macro, it only print if the debug level is as high
+ * as required by the first field. Again the definition is
+ * variadric and if the debug level is 0 we reduce the macro to
+ * the empty instruction.
+ *
+ * */
+/** @{ */
+/** @file
+ * */
+/* ========================================================================= */
+
+#ifndef __EG_MACROS_H__
+#define __EG_MACROS_H__
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <setjmp.h>
+#include <errno.h>
+
+/* ========================================================================= */
+/** @brief return the offset of a member inside a structure.
+ * @param type the type of the containing structure.
+ * @param member the name of the member that we are interested in compute the
+ * offset.
+ * @return the number of bytes between the member and the beginning of the
+ * structure. */
+#define EGoffsetOf(__type,__member) ((size_t) &((__type *)0)->__member)
+
+/* ========================================================================= */
+/** @brief given a pointer to a member of a structure, return the pointer to
+ * the head of the structure. (idea taken from Linux Kernel).
+ * @param __ptr pointer to the member of the containing structure.
+ * @param __type name type of the containing structure.
+ * @param __member name of the given member in the containing structure.
+ * @return pointer to the containing structure.
+ * */
+#define EGcontainerOf(__ptr,__type,__member) ({\
+ typeof(((__type *)0)->__member) *const __EGcOf_ptr = (__ptr);\
+ (__type *)( (char*)__EGcOf_ptr - ((size_t) &((__type *)0)->__member));})
+
+/* ========================================================================= */
+/** @brief retrieve the data of type '__TYPE' in the structure '__DATA' that is
+ * located in the offset '__OFFS'. */
+#define EGosGetData(__DATA,__OFFS,__TYPE) (*((__TYPE*)(((char*)__DATA)+__OFFS)))
+
+/* ========================================================================= */
+/** @brief set the data of type '__TYPE' in the structure '__DATA' that is
+ * located in the offset '__OFFS' to the value 'val'. */
+#define EGosSetData(__DATA,__OFFS,__TYPE,val) (EGosGetData(__DATA,__OFFS,__TYPE)=val)
+
+/* ========================================================================= */
+/** @brief Defione copy functions, these functions
+ * return copy of objects but with independent storage space, there are two
+ * versions, one that require a memory pool from where to look for memory, and
+ * another where we don't care about that.... the place from where the memory
+ * was asked for depend on the function, se the function definition for
+ * details.
+ * Note that if the is no more memory available the function should call
+ * exit(EXIT_FAILURE).
+ * This is only intended as a readibility help */
+typedef void *(*EGcopy_f) (void *p);
+
+/* ========================================================================= */
+/** @brief Define a null copy function */
+#define nullCopy ((EGcopy_f)0)
+
+/* ========================================================================= */
+/** @name Algorithms Return Status
+ * Here we define some general status for algorithms, the exact meaning should
+ * be sought in the actual algorithm definition, but the definitions here
+ * provide a first overview of their meaning. */
+/* @{ */
+/** @brief the algorithm finish successfully. */
+#define EG_ALGSTAT_SUCCESS 0
+/** @brief the algorithm could only partially finish */
+#define EG_ALGSTAT_PARTIAL 1
+/** @brief the algorithm stop because of some numerical problem */
+#define EG_ALGSTAT_NUMERROR 2
+/** @brief the algorithm stop because of some unforeseen error */
+#define EG_ALGSTAT_ERROR 3
+/* @} */
+
+/* ========================================================================= */
+/** @name Mathematical Constants
+ * Here we define some mathematical constants needed in some parts of the code
+ * that are of general use */
+/* @{ */
+/** @brief definition of \f$\pi\f$ as a constant, suitable for quad-IEEE
+ * operations. */
+#define EG_M_PI 3.1415926535897932384626433832795029L
+/* @} */
+
+/* ========================================================================= */
+/** @brief Call macro. The idea is to replace the following call:
+ * rval = myfunction(mypar);
+ * CHECKRVALG(rval,mygoto);
+ * with the call
+ * EGcall(rval,mygoto,myfunction(mypar));
+ * this should help simplify calls and clean-up the code
+ * @note each parameter is evaluated once, thus ensuring correct evaluation of
+ * parameters, even if they are an expresion. */
+#define EGcall(__rval__,__cleanup__,__myfunc__) do{const int __EGrval__=__myfunc__;(__rval__)=__EGrval__;TESTG(__EGrval__,__cleanup__,"Function " #__myfunc__ " failed with code %d ",__EGrval__);}while(0)
+/* ========================================================================= */
+/** @brief call macro with default arguments, it assumes that rval is an
+ * integer variable to be used to store return value, and CLEANUP is a valid
+ * label for an exit point in the code */
+#define EGcallD(__myfunc2__) EGcall(rval,CLEANUP,__myfunc2__)
+/* ========================================================================= */
+/** @brief Display information about the library and the running process */
+void EGlib_info(void);
+/* ========================================================================= */
+/** @brief print versioning info of the library */
+void EGlib_version(void);
+/* ========================================================================= */
+/** @brief needed global jump-control variable */
+extern jmp_buf __EGljmp;
+/* ========================================================================= */
+/** @brief a generic signal handler, it can handle SIGXCPU, SIGINT and SIGSEGV
+ * signals by displaying a proper indication to stderr; note that a call to
+ * #EGsigSetjmp should be performed at the very beggining of the main function
+ * for this to be robust.
+ * When receiving a SIGXCPU, SIGINT signal, the function report the signal and jump-back
+ * to the setjmp position.
+ * When receiving a SIGINT signal, the function report the signal and jump-back
+ * @param s the signal number received
+ * */
+void EGsighandler(int s);
+/* ========================================================================= */
+/** @brief use #EGsighandler for SIGXCPU, SIGINT and SIGSEGV as signal handler.
+ * */
+void __EGsigSetSignal(void);
+/* ========================================================================= */
+/** @brief set the jump point, and the sginal handler.
+ * it must receive a label where to jump, and where
+ * to save the returning status, typically this will be the clean-up section
+ * of the main function and the status variable in the mian program.
+ * @param __status__ the returning status of the call, zero when set, non-zero
+ * when comming back from a long-jump.
+ * @param __LABEL__ where to jump when returning from a long-jump. */
+#define EGsigSet(__status__,__LABEL__) do{MESSAGE(0,"setjmp here");if((__status__=setjmp(__EGljmp))){IFMESSAGE(1,"Back from signal handler, status %d",__status__); goto __LABEL__;}__EGsigSetSignal();}while(0)
+/* ========================================================================= */
+/** @brief set memory and run-time limits (soft and hard); if the current
+ * limits are bellow the porposed limits, it will warn on screen, but will not
+ * fail. Note that this function will set RLMIT_CORE to zero.
+ * @param max_rtime maximum running time.
+ * @param mem_limit maximum memory allowed for the process, this include
+ * RLIMIT_AS and RLIMIT_DATA.
+ * */
+void EGsetLimits(double max_rtime, unsigned long memlimit);
+/* ========================================================================= */
+/** @brief given a constant array-base, an element size, and a position,
+ * return the pointer to the appropiate element */
+#define EGaGetCElem(__EGabase__,__EGasz__,__EGaelem__) ((const char*)(((const char*)(__EGabase__))+((const size_t)(__EGasz__))*((const size_t)(__EGaelem__))))
+/* ========================================================================= */
+/** @brief given an array-base, an element size, and a position, return the
+ * pointer to the appropiate element */
+#define EGaGetElem(__EGabase__,__EGasz__,__EGaelem__) ((char*)(((char*)(__EGabase__))+((const size_t)(__EGasz__))*((const size_t)(__EGaelem__))))
+/* ========================================================================= */
+/** @brief given an array base, an element size, and a pointer, return the
+ * position of the element on the array */
+#define EGaGetPos(__EGabase__,__EGasz__,__EGaptr__) ((((char*)(__EGaptr__))-((char*)(__EGabase__)))/((const size_t)(__EGasz__)))
+/* ========================================================================= */
+/** @} */
+/* end of eg_macros.h */
+#endif
diff --git a/qsopt_ex/eg_mem.h b/qsopt_ex/eg_mem.h
new file mode 100644
index 0000000..42c4896
--- /dev/null
+++ b/qsopt_ex/eg_mem.h
@@ -0,0 +1,194 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ *
+ * 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
+ * */
+/* ========================================================================= */
+/** @defgroup EGmem EGmem
+ *
+ * Here we define some usefull macros to deal with memory issues, for example,
+ * assert that we always return memory when posible, and if no memory is found,
+ * then we just exit to the system (because if there is trully no memory....
+ * there is no much else to do... unless we start using shrinkable memory
+ * pools, like for example @ref EGmemSlab , but that is still a long way off,
+ * it will also perform (if debugging enabled) some allocation / freeing
+ * checkings and so on.
+ *
+ * @version 0.0.1
+ * @par History:
+ * -2005-09-05
+ * - Add EGrealloc, wich is a wrapper of realloc but that assures us
+ * to have memory, if there is no memory, we exit. The idea of these
+ * functions is that in the future they would interact with the
+ * memory pools to use any memory still in the pools.
+ * -2005-08-20
+ * - Move memory align definitions here, and set the aligment of
+ * memory to 8 bytes (i.e. 64 bits). This is to simplify compilation
+ * in diferent architectures like Sun, opteron 64 and intel 32.
+ * -2005-08-01
+ * - Fix calloc call to the right type (size_t), and some printing
+ * issues while compiling on 64-bit architectures.
+ * -2005-07-30
+ * - First Implementation
+ * */
+/** @file
+ * @ingroup EGmem */
+/** @addtogroup EGmem */
+/** @{ */
+#ifndef __EG_MEM_H__
+#define __EG_MEM_H__
+
+#include "eg_macros.h"
+
+/* ========================================================================= */
+/** @brief size of a normal word in this machine (a word is just big enough to
+ * store a pointer) */
+#define EG_MEM_WORD_SIZE (sizeof(void*))
+/* ========================================================================= */
+/** @brief memory aligment used by EG alloc functions. */
+#define EG_MEM_ALIGNMENT 8U
+
+/* ========================================================================= */
+/** @brief \f$log_2(EG_MEM_ALIGNMENT)\f$. */
+#define EG_MEM_ALIGNMENT_SHIFT 3U
+
+/* ========================================================================= */
+/** @brief Given a pointer, return it's aligned value. */
+#define EG_MEM_ALIGN(__ptr) \
+ ((((size_t)__ptr)+EG_MEM_ALIGNMENT-1)&(~(EG_MEM_ALIGNMENT-1)))
+
+/* ========================================================================= */
+/** @brief type of the free functions that recive only one parameter */
+typedef void (*EGfree_f) (void *);
+
+/* ========================================================================= */
+/** @brief this is the the data free that does nothing, use it when you don't
+ * want/need to free the internal list data becouse you will do it
+ * elsewere */
+#define nullFree ((EGfree_f)0)
+
+/* ========================================================================= */
+/** @brief custom allocation functions prototype: This class of functions
+ * receive some user-provided data (udata), and given a size (psz), return a pointer of the given size */
+typedef void*(*EGualloc_f)(void*udata,size_t psz);
+
+/* ========================================================================= */
+/** @brief custom free functions prototype: This class of functions receive
+ * some user-provided data (udata), and a pointer (ptr), and should free (or
+ * manage de-alocation) of the provided pointer. */
+typedef void (*EGufree_f)(void*udata,void*ptr);
+
+/* ========================================================================= */
+/** @brief type for constructor functions. Given a pointer to an element of
+ * some type, do the internal initialization necesary so that we can work with
+ * the lement, such initialization may include allocating some internal memory
+ * needed by the structure (not done by the user). This functions must never
+ * fail. if some unexpected error does happen inside, then the function should
+ * not return. (a call to exit(1) would do the trick). */
+typedef void (*EGconstructor_f) (void *);
+
+/* ========================================================================= */
+/** @brief Null constructor function (do nothing) */
+#define nullConstructor ((EGconstructor_f)0)
+
+/* ========================================================================= */
+/** @brief type for destructor functions. Given a pointer to an element of some
+ * type, free all internal memory related to the element allocated during the
+ * construction phase. (but not the pointer itself). This function must always
+ * succed, if an error happen, the function should never return. (a call to
+ * exit(1) would do the trick). */
+typedef void (*EGdestructor_f) (void *);
+
+/* ========================================================================= */
+/** @brief Null destructor function (do nothing) */
+#define nullDestructor ((EGdestructor_f)0)
+
+/* ========================================================================= */
+/** @brief this function replace malloc, check if the memory is not zero, if
+ * it is, it exit from the program, and display who called it and how much
+ * memory it tryed to alloc.
+ * @param __A number of bytes to allocate.
+ * @return a void* pointer to the newly allocated memory, note that if the
+ * function returns at all, it will return with the amount of memory required,
+ * so no NULL checking is ever necesary after an EGmalloc call.
+ * */
+#define EGmalloc(__A) ({\
+ size_t const _EGmp_sz_ = (size_t)(__A);\
+ void * _EGmp_res_ = 0;\
+ /*WARNINGL(0,!_EGmp_sz_,"Allocating 0 bytes");*/\
+ if(_EGmp_sz_)\
+ {\
+ _EGmp_res_ = calloc((size_t)1,_EGmp_sz_);\
+ EXIT(!_EGmp_res_,"Not enough memory while allocating %zd bytes",_EGmp_sz_);\
+ }\
+ _EGmp_res_;})
+
+/* ========================================================================= */
+/** @brief This function allocate 'count' elements of type 'type' and return
+ * a pointer of type 'type*'. If the memory is not available the program will
+ * exit indicating where it was trying to get memory and how much, it will also
+ * check some common errors like allocating zero bytes.
+ * @param __type type of the element required.
+ * @param __count number of contiguous elements of the given type required.
+ * @return pointer to the beggining of the allocated array of the apropiate
+ * type (so no casting is needed). Note that if this function returns at all,
+ * then the memory has been allocated and thus no NULL checking return is
+ * necesary. */
+#define EGsMalloc(__type,__count) (__type*)EGmalloc(sizeof(__type)*((size_t)(__count)))
+
+/* ========================================================================= */
+/** @brief Realloc a given pointer to the new size, and check that we find
+ * enough memory to return. If we don't, we exit the execution.
+ * @param __ptr pointer to reallocate.
+ * @param __sz new number of bytes to reallocate.
+ * @return pointer to the new block of memory */
+#define EGrealloc(__ptr,__sz) ({\
+ const size_t ____sz = (size_t)(__sz);\
+ (__ptr) = realloc((__ptr),____sz);\
+ EXIT(!(__ptr)&&(____sz),"not enough memory while reallocating %zd",____sz);\
+ (__ptr);})
+
+/* ========================================================================= */
+/** @brief this is used to enable malloc/free tracking and extra debugging */
+#ifndef __EG_MEM_FREE_CHECK__
+#define __EG_MEM_FREE_CHECK__ (1 && DEBUG)
+#endif
+
+/* ========================================================================= */
+/** @brief This function replace free, the idea of this is to HOPEFULLY later
+ * develop a memory leack checker that tell us who and where asked for memory
+ * and didn't free it, in hte meantime they do nothing.
+ * @param __A pointer to the piece of memory to be freed, if debuging is enabled,
+ * the function will test for freing NULL pointers, for suspicios address
+ * freing and so on. note that the given pointer will point to NULL after this
+ * call, thus reducing the posibility of freeing multiple times the same piece
+ * of memory, or of allocating it after freeing it. */
+#if __EG_MEM_FREE_CHECK__
+#define EGfree(__A) ({\
+ EXIT(((__A) && !(((size_t)(__A))>>19)),"Trying to free pointer "#__A\
+ " with value %zd\nThis is probably an error",(size_t)(__A));\
+ if(__A) free(__A);\
+ else WARNING(1,"Trying to free "#__A", a NULL pointer");\
+ (__A) = 0;})
+#else
+#define EGfree(__A) ({free(__A);(__A)=0;})
+#endif
+
+/* ========================================================================= */
+/* end of eg_mem.h */
+/** @} */
+#endif
diff --git a/qsopt_ex/eg_memslab.c b/qsopt_ex/eg_memslab.c
new file mode 100644
index 0000000..4a1857f
--- /dev/null
+++ b/qsopt_ex/eg_memslab.c
@@ -0,0 +1,327 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2008 Daniel Espinoza.
+ *
+ * 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
+ * */
+/* ========================================================================= */
+/** @file
+ * @ingroup EGmemSlab */
+/** @addtogroup EGmemSlab */
+/** @{ */
+/* ========================================================================= */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <inttypes.h> /* For printf format support */
+
+#include "eg_memslab.h"
+
+#include "logging-private.h"
+
+/* ========================================================================= */
+int EGmemSlabPoolSetParam(EGmemSlabPool_t*const pool,
+ const int param,
+ const int val)
+{
+ int rval = 0;
+ switch(param)
+ {
+ case EG_MSLBP_FREEFREE:
+ __EGmspLock(pool);
+ if(val) pool->freefree = 1;
+ else pool->freefree = 0;
+ __EGmspUnlock(pool);
+ break;
+ default:
+ rval = 1;
+ MESSAGE(0,"Unknown parameter %d",param);
+ break;
+ }
+ EG_RETURN(rval);
+}
+/* ========================================================================= */
+void EGmemSlabDisplay(const EGmemSlab_t*const slab)
+{
+ const size_t n_elem = slab->control.pool ? slab->control.pool->n_elem : (size_t)0;
+ const size_t n_elem2 = (n_elem/8)*8;
+ register size_t i;
+ QSlog("Slab %p:", (const void*const)slab);
+ QSlog("\t->base : %8p", (void*)(slab->control.base));
+ QSlog("\t->elem_sz : %8zd", slab->control.elem_sz);
+ QSlog("\t->n_elem : %8zd", slab->control.n_elem);
+ QSlog("\t->slab_cn : [%8p,%8p]",
+ (void*)(slab->control.slab_cn.prev),
+ (void*)(slab->control.slab_cn.next));
+ QSlog("\t->pool : %8p", (void*)(slab->control.pool));
+ QSlog("\t->next : %8zd", slab->control.next);
+ QSlog("\t->next_list:");
+ for( i = 0 ; i < n_elem2 ; i+= 8)
+ {
+ QSlog("\t[%3zu]=%3u [%3zu]=%3u [%3zu]=%3u [%3zu]=%3u "
+ "[%3zu]=%3u [%3zu]=%3u [%3zu]=%3u [%3zu]=%3u",
+ i, ((unsigned)(slab->next_list[i])),
+ i+1, ((unsigned)(slab->next_list[i+1])),
+ i+2, ((unsigned)(slab->next_list[i+2])),
+ i+3, ((unsigned)(slab->next_list[i+3])),
+ i+4, ((unsigned)(slab->next_list[i+4])),
+ i+5, ((unsigned)(slab->next_list[i+5])),
+ i+6, ((unsigned)(slab->next_list[i+6])),
+ i+7, ((unsigned)(slab->next_list[i+7])));
+ }
+ QSlog("\t");
+ for( ; i < n_elem ; i++)
+ {
+ QSlog("[%3zu]=%3u ",i, ((unsigned)(slab->next_list[i])));
+ }
+}
+/* ========================================================================= */
+void __EGmemSlabInit( EGmemSlab_t*const slab,
+ EGmemSlabPool_t*const Pool)
+{
+ const EGconstructor_f _EGconstr = Pool->constr;
+ const size_t elem_sz = Pool->elem_sz;
+ const size_t n_elem = Pool->n_elem;
+ register size_t i;
+ char*base = (char*)(EG_MEM_ALIGN(sizeof(EGmsbControl_t)+Pool->n_elem) +
+ (char*)(slab) + (Pool->c_color));
+ slab->control.base = base;
+ slab->control.elem_sz = elem_sz;
+ slab->control.n_elem = 0;
+ EGeListAddAfter(&(slab->control.slab_cn),&(Pool->empty));
+ slab->control.pool = Pool;
+ slab->control.next = 0;
+ /* now we initialize all elements and list of next elements */
+ for( i = 0 ; i < n_elem; i++)
+ {
+ slab->next_list[i] = (uint8_t)(i+1);
+ if(_EGconstr)
+ {
+ _EGconstr(base);
+ base += elem_sz;
+ }
+ }
+ slab->next_list[n_elem-1] = EG_SLAB_ENDMARK;
+ /* if we are profiling, update here */
+ #if EG_SLAB_PROFILE <= DEBUG
+ slab->control.pool->n_allocs++;
+ slab->control.pool->n_slabs++;
+ if(slab->control.pool->max_slabs < slab->control.pool->n_slabs)
+ slab->control.pool->max_slabs = slab->control.pool->n_slabs;
+ #endif
+ /* change current color in main pool */
+ Pool->c_color += (uint8_t)(EG_MEM_ALIGNMENT);
+ if(Pool->c_color > Pool->max_color) Pool->c_color = 0;
+ if(EG_SLAB_VERBOSE <= DEBUG)
+ {
+ QSlog("Initializing slab as:");
+ EGmemSlabDisplay(slab);
+ }
+}
+/* ========================================================================= */
+void EGmemSlabClear( EGmemSlab_t*slab)
+{
+ const EGdestructor_f _EGdest = slab->control.pool->dest;
+ const size_t elem_sz = slab->control.elem_sz;
+ const size_t n_elem = slab->control.pool->n_elem;
+ char*base = slab->control.base;
+ register size_t i = n_elem;
+ if(EG_SLAB_VERBOSE <= DEBUG)
+ {
+ QSlog("slab before clearing:");
+ EGmemSlabDisplay(slab);
+ }
+ WARNINGL( EG_SLAB_DEBUG, slab->control.n_elem,
+ "Clearing slab at %p with %zd elements of size %zd",
+ (void*)slab, slab->control.n_elem, elem_sz);
+ /* clear each element */
+ if(_EGdest)
+ {
+ while(i--)
+ {
+ _EGdest(base);
+ base += elem_sz;
+ }
+ }
+ /* remove the slab from it's containing list */
+ EGeListDel(&(slab->control.slab_cn));
+ /* if we are profiling, update here */
+ #if EG_SLAB_PROFILE <= DEBUG
+ slab->control.pool->n_slabs--;
+ #endif
+ /* if we are debugging, poison all data */
+ if(EG_SLAB_DEBUG <= DEBUG)
+ {
+ slab->control.base = (char*)EG_SLAB_POISON;
+ slab->control.slab_cn = (EGeList_t){(void*)EG_SLAB_POISON,(void*)EG_SLAB_POISON};
+ slab->control.next = EG_SLAB_ENDMARK;
+ for( i = n_elem ; i-- ; ) slab->next_list[i] = EG_SLAB_ENDMARK;
+ }
+ /* and display if needed */
+ if(EG_SLAB_VERBOSE <= DEBUG)
+ {
+ QSlog("slab after clearing:");
+ EGmemSlabDisplay(slab);
+ }
+ if(EG_SLAB_DEBUG <= DEBUG)
+ slab->control.pool = (EGmemSlabPool_t*)EG_SLAB_POISON;
+}
+/* ========================================================================= */
+/** @brief Initialize the profiling data of a slab pool */
+#if EG_SLAB_PROFILE <= DEBUG
+#define EGmemSlabPoolInitProfile(_EGmPl, __sz, __file, __func, __line) ({\
+ _EGmPl->file = __file;\
+ _EGmPl->func = __func;\
+ _EGmPl->line = __line;\
+ _EGmPl->real_sz = __sz;\
+ _EGmPl->n_slabs = _EGmPl->n_tot = _EGmPl->max_tot = _EGmPl->max_slabs = \
+ _EGmPl->ncals = _EGmPl->n_allocs = 0;})
+#else
+#define EGmemSlabPoolInitProfile(_EGmPl, __sz, __file, __func, __line)
+#endif
+
+/* ========================================================================= */
+void __EGmemSlabPoolInit( EGmemSlabPool_t*const pool,
+ const size_t sz,
+ EGconstructor_f constr_fn,
+ EGdestructor_f dest_fn,
+ const char*const file,
+ const char*const func,
+ const int line)
+{
+ const size_t elem_sz = sz < EG_SLAB_LLIMIT ? EG_SLAB_LLIMIT: EG_MEM_ALIGN(sz);
+ const size_t n_elem = (EG_SLAB_SIZE - EG_MEM_ALIGN(sizeof(EGmsbControl_t)))/
+ (elem_sz +1);
+ /* check that the real element size is within bounds */
+ if(elem_sz > EG_SLAB_ULIMIT)
+ {
+ QSlog("ERROR: Trying to initializate slab pool with element size"
+ " %zd > %zd (hard upper limit)", elem_sz, EG_SLAB_ULIMIT);
+ exit(EXIT_FAILURE);
+ }
+ /* initialize the structure */
+ #if HAVE_EG_THREAD
+ pthread_mutex_init(&(pool->mt),0);
+ #endif
+ __EGmspLock(pool);
+ EGeListInit(&(pool->half));
+ EGeListInit(&(pool->empty));
+ EGeListInit(&(pool->full));
+ pool->constr = constr_fn;
+ pool->dest = dest_fn;
+ pool->elem_sz = (uint16_t)(elem_sz);
+ pool->n_elem = (uint8_t)(n_elem);
+ pool->c_color = 0;
+ pool->max_color = ((uint8_t)(EG_SLAB_SIZE - EG_MEM_ALIGN(sizeof(EGmsbControl_t)+ n_elem) -
+ (elem_sz*n_elem)));
+ pool->freefree = 1;
+ EGmemSlabPoolInitProfile(pool,sz, file, func, line);
+ /* verbose output */
+ if(EG_SLAB_VERBOSE <= DEBUG )
+ EGmemSlabPoolDisplay(pool);
+ __EGmspUnlock(pool);
+}
+/* ========================================================================= */
+void EGmemSlabPoolClear(EGmemSlabPool_t*const Pool)
+{
+ void* _EGptr;
+ __EGmspLock(Pool);
+ while(!EGeListIsEmpty(&(Pool->half)))
+ {
+ _EGptr = EGmemSlabGetSlab(Pool->half.next);
+ EGmemSlabClear(_EGptr);
+ free(_EGptr);
+ }
+ while(!EGeListIsEmpty(&(Pool->empty)))
+ {
+ _EGptr = EGmemSlabGetSlab(Pool->empty.next);
+ EGmemSlabClear(_EGptr);
+ free(_EGptr);
+ }
+ while(!EGeListIsEmpty(&(Pool->full)))
+ {
+ _EGptr = EGmemSlabGetSlab(Pool->full.next);
+ EGmemSlabClear(_EGptr);
+ free((void*)EG_SLAB_PAGE(_EGptr));
+ }
+ /* verbose output */
+ if(EG_SLAB_VERBOSE <= DEBUG || EG_SLAB_PROFILE <= DEBUG)
+ {
+ QSlog("After clearing slab pool:");
+ EGmemSlabPoolDisplay(Pool);
+ }
+ __EGmspUnlock(Pool);
+}
+/* ========================================================================= */
+void EGmemSlabPoolShrink(EGmemSlabPool_t*const Pool)
+{
+ void* _EGptr;
+ __EGmspLock(Pool);
+ while(!EGeListIsEmpty(&(Pool->empty)))
+ {
+ _EGptr = EGmemSlabGetSlab(Pool->empty.next);
+ EGmemSlabClear(_EGptr);
+ free((void*)EG_SLAB_PAGE(_EGptr));
+ }
+ __EGmspUnlock(Pool);
+}
+/* ========================================================================= */
+void EGmemSlabPoolDisplay(const EGmemSlabPool_t*const pool)
+{
+ QSlog("Pool %p:", (const void*const)pool);
+ QSlog("\t->half : [%8p,%8p]",
+ (void*)(pool->half.prev),
+ (void*)(pool->half.next));
+ QSlog("\t->empty : [%8p,%8p]",
+ (void*)(pool->empty.prev),
+ (void*)(pool->empty.next));
+ QSlog("\t->full : [%8p,%8p]",
+ (void*)(pool->full.prev),
+ (void*)(pool->full.next));
+ QSlog("\t->constr : %8p", (void*)(pool->constr));
+ QSlog("\t->dest : %8p", (void*)(pool->dest));
+ QSlog("\t->elem_sz : %8"PRIu16, pool->elem_sz);
+ QSlog("\t->n_elem : %8"PRIu8, pool->n_elem);
+ QSlog("\t->c_color : %8"PRIu8, pool->c_color);
+ QSlog("\t->max_color : %8"PRIu8, pool->max_color);
+ QSlog("\t->freefree : %8"PRIu8, pool->freefree);
+ #if EG_SLAB_PROFILE <= DEBUG
+ if(pool->ncals)
+ {
+ QSlog("\t->file : %s", pool->file);
+ QSlog("\t->func : %s", pool->func);
+ QSlog("\t->line : %8d", pool->line);
+ QSlog("\t->real_sz : %8"PRIu64, pool->real_sz);
+ QSlog("\t->n_slabs : %8"PRIu64, pool->n_slabs);
+ QSlog("\t->n_tot : %8"PRIu64, pool->n_tot);
+ QSlog("\t->max_tot : %8"PRIu64, pool->max_tot);
+ QSlog("\t->max_slabs : %8"PRIu64, pool->max_slabs);
+ QSlog("\t->ncals : %8"PRIu64, pool->ncals);
+ QSlog("\t->n_allocs : %8"PRIu64, pool->n_allocs);
+ QSlog("\tEficiency :");
+ QSlog("\t\talloc ratio : %8lg (%"PRIu64"/%"PRIu64")",
+ ((double)pool->ncals)/pool->n_allocs, pool->ncals, pool->n_allocs);
+ QSlog("\t\tmemory waste : %8.3lf %%",
+ 100*(1-((double)pool->max_tot*pool->real_sz)/
+ ((double)pool->max_slabs*EG_SLAB_SIZE)));
+ }
+ #endif
+}
+/* ========================================================================= */
diff --git a/qsopt_ex/eg_memslab.h b/qsopt_ex/eg_memslab.h
new file mode 100644
index 0000000..5c2d05b
--- /dev/null
+++ b/qsopt_ex/eg_memslab.h
@@ -0,0 +1,418 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005,2006,2007,2008,2009,2010,2011 Daniel Espinoza.
+ *
+ * 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
+ * */
+/* ========================================================================= */
+/** @defgroup EGmemSlab EGmemSlab
+ *
+ * This is a basic interface for slab pool managment. The idea comes from Slabs
+ * as defined in both Linux and Solaris (see "The Slab Allocator: An
+ * Object-Caching Kernel Memory Allocator", by Jeff Bonwick, Sun Microsystems),
+ * the basic idea is
+ * to provide pool for a specific type of object, and to store them in an
+ * initialized state, so that initialization and destruction only is done while
+ * growing/freeing the memory slabs, thus this approach should provide greater
+ * advantages for complitated to initialize structures. and in theory
+ * (althought not yet implemented) this structure can be managed so as to
+ * provide a shrinkable memory managment on the fly.
+ *
+ * In this implementation we only allow small caches (i.e. objects must be
+ * smaller than EG_SLAB_ULIMIT and internally we don't allocate objects smaller
+ * than EG_SLAB_LLIMIT),
+ * within a unique memory page. We could allow in the future for more flexible
+ * slabs. This implementation also uses colored slabs (see the paper for
+ * further details).
+ *
+ * Here we can see a schematic drawing of the slab allocator structure and
+ * functions:
+ *
+ * @version 0.9.0
+ * @par History:
+ * - 2011-03-01
+ * - Make EGms_t thread-safe, i.e. a single memory pool can serve
+ * several threads. This makes the default memory manager for GMP
+ * thread safe as well
+ * - 2010-12-27
+ * - Add short-hand names for functions
+ * - 2008-10-06
+ * - Second implementation
+ * - 2005-07-30
+ * - First Implpementation.
+ * */
+/** @file
+ * @ingroup EGmemSlab */
+/** @addtogroup EGmemSlab */
+/** @{ */
+/** @example eg_memslab.ex.c */
+/* ========================================================================= */
+#ifndef __EG_MEM_SLAB_H__
+#define __EG_MEM_SLAB_H__
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include "eg_mem.h"
+#include "eg_elist.h"
+
+/* ========================================================================= */
+/** @name EGmemSlab Parameters
+ * @brief parameters for controling slab pool allocation */
+/* @{ */
+/** @brief control the handle of empty slabs, if set to non-zero, free unused
+ * slabs as they become unused, if set to zero, keep all unused slabs until
+ * #EGmemSlabPoolShrink is called */
+#define EG_MSLBP_FREEFREE 1
+/* @} */
+/* ========================================================================= */
+/* declare the slab pool structure */
+struct EGmemSlabPool_t;
+
+/* ========================================================================= */
+/** @brief maximum size of the objects that can be allocated via slab. */
+#define EG_SLAB_ULIMIT ((size_t)1023)
+#define EG_SLAB_LLIMIT ((size_t)16)
+
+/* ========================================================================= */
+/** @brief size of the memory slabs (in bytes ) */
+#define EG_SLAB_SIZE ((size_t)0x1000)
+
+/* ========================================================================= */
+/** @brief mask to detect the position of a piece of memory within a slab */
+#define EG_SLAB_MASK (~(EG_SLAB_SIZE-1))
+
+/* ========================================================================= */
+/** @brief address used to check consistency if enabled */
+#define EG_SLAB_POISON ((size_t)0xdeadbeef)
+
+/* ========================================================================= */
+/** @brief if set to one, enable profiling for the slab allocator */
+#define EG_SLAB_PROFILE 1000
+
+/* ========================================================================= */
+/** @brief local verbose level for the slab allocator, the lower the level, the
+ * more information will be printed on screen. */
+#define EG_SLAB_VERBOSE 1000
+
+/* ========================================================================= */
+/** @brief local debug level for the slab allocator, the lower the level, the
+ * more testing will be done. */
+#define EG_SLAB_DEBUG 1000
+
+/* ========================================================================= */
+/** @brief end of list marker, note that this can not be more than 255 */
+#define EG_SLAB_ENDMARK ((uint8_t)255U)
+
+#ifndef EG_SLAB_REDUCE_TO_MALLOC
+/* ========================================================================= */
+/** @brief if set to one, reduce the slab pool allocator to a simple malloc
+ * call */
+#define EG_SLAB_REDUCE_TO_MALLOC 0
+#endif
+
+
+/* ========================================================================= */
+/** @brief Given a pointer, return a pointer to the beginning of the containing
+ * page. */
+#define EG_SLAB_PAGE(__ptr) (((size_t)__ptr)&EG_SLAB_MASK)
+
+/* ========================================================================= */
+/** @brief structure that holds the information relevant to each slab
+ * */
+typedef struct
+{
+ char*base; /**< @brief Where the data-payload start */
+ size_t elem_sz; /**< @brief byte-size of each element */
+ size_t n_elem; /**< @brief number of used elements */
+ EGeList_t slab_cn; /**< @brief Connector into the list of slabs*/
+ struct EGmemSlabPool_t *pool; /**< Pointer to the slab pool structure */
+ size_t next; /**< @brief next free element */
+} EGmsbControl_t;
+typedef struct
+{
+ EGmsbControl_t control; /**< @brief comon base structure for slabs */
+ uint8_t next_list[]; /**< @brief list of free elements, the next
+ element is next_list[0], whenever we reach a
+ value of 255, it is the end of the free-list.
+ */
+} EGmemSlab_t;
+
+/* ========================================================================= */
+/** @brief structure used to store a slab memory pool */
+typedef struct EGmemSlabPool_t
+{
+ EGeList_t half; /**< Head of the list for half-full slabs */
+ EGeList_t empty; /**< Head of the list for non used slabs */
+ EGeList_t full; /**< Head of the list for fully used slabs*/
+ EGconstructor_f constr; /**< Constructor for the local elements */
+ EGdestructor_f dest; /**< Destructor for the local elements */
+ uint16_t elem_sz; /**< Size of the elements in the slab, including
+ extra space for pointer to next. */
+ uint8_t n_elem; /**< Total number of elements in each slab */
+ uint8_t c_color; /**< Last used color while creating slabs. */
+ uint8_t max_color; /**< Maximum valid value for colors in this pool */
+ uint8_t freefree:1; /**< if non-zero, free non-used slabs */
+ uint8_t pad1:7; /**< padding */
+ uint16_t pad2; /**< padding */
+ char const *file; /**< File where the structure was initialized */
+ char const *func; /**< Function where the structure was initialized */
+ int line; /**< Line where the structure was initialized */
+ uint64_t real_sz; /**< Actual size of the elements asked by the user */
+ uint64_t n_slabs; /**< Number of slabs */
+ uint64_t n_tot; /**< Total number of elements in use by the user */
+ uint64_t max_tot; /**< Maximum number of elements allocated */
+ uint64_t max_slabs; /**< Maximum number of slabs used */
+ uint64_t ncals; /**< number to alloc calls */
+ uint64_t n_allocs; /**< number slab alloc calls */
+ #if HAVE_EG_THREAD
+ pthread_mutex_t mt; /**< mutex for memory slab manager */
+ #endif
+}
+EGmemSlabPool_t;
+
+/* ========================================================================= */
+/** @brief slab lock/unlock macros */
+#if HAVE_EG_THREAD
+#define __EGmspLock(__slab) pthread_mutex_lock(&(__slab->mt))
+#define __EGmspUnlock(__slab) pthread_mutex_unlock(&(__slab->mt))
+#else
+#define __EGmspLock(__slab)
+#define __EGmspUnlock(__slab)
+#endif
+/* ========================================================================= */
+/** @brief display given slab structure
+ * @param slab what to display
+ * */
+void EGmemSlabDisplay(const EGmemSlab_t*const slab);
+
+/* ========================================================================= */
+/** @brief display given pool structure
+ * @param pool what to display
+ * */
+void EGmemSlabPoolDisplay(const EGmemSlabPool_t*const pool);
+
+/* ========================================================================= */
+/** @brief given a piece of memory that should be within a slab, return the
+ * pointer to the related slab structure, remember that the slab structure is
+ * at the beggining of the page. */
+#define EGmemSlabGetSlab(__ptr) \
+ ((EGmemSlab_t*)(EG_SLAB_PAGE(__ptr)))
+
+/* ========================================================================= */
+/** @brief initialize a slab structure. This include calling the constructor
+ * for all elements in the slab. Note that this function asumes that all memory
+ * has been previously set to NULL. It will also place this slab in the list
+ * of empty slabs in the given pool.
+ * @param slab pointer within the memory range of the slab to be initialized.
+ * @param __Pool Slab __Pool where this slab will bellong from. The slab pool
+ * should be initialized (i.e. should have a constructor and destructor, and an
+ * element size set.
+ * */
+void __EGmemSlabInit( EGmemSlab_t*const slab,
+ EGmemSlabPool_t*const __Pool);
+/* ========================================================================= */
+/** @brief given an initialized slab, clear all internally allocated memory,
+ * and leave the slab ready to be freed by 'free', this include calling the
+ * destructor for all elements in the slab.
+ * @param slab pointer to an area of the slab memory to be clear.
+ * @note If debugging is enabled, then all fields will be poisoned so that
+ * subsequent use of this structure will fail (but for the free call). Also, if
+ * debugging is enabled, we will check that the slab has no element in use.
+ * */
+void EGmemSlabClear( EGmemSlab_t*const slab);
+
+/* ========================================================================= */
+/** @brief Given a non-full slab, extract a pointer to the next unused element
+ * in the slab, and update all internal data. and if it becomes full, then move
+ * it to the full list within the pool. Also, if debugging, poison the pointer
+ * to the enext element in the returned element. If the slab is not full, and
+ * the number of active elements is one, then move the slab to the half-full
+ * slab list in the pool.
+ * @param slab pointer within a slab memory.
+ * @return pointer to a void* of initialized memory by the given contructor in
+ * the slab pool.
+ * */
+#define EGmemSlabPopElement(slab) ({\
+ EGmemSlab_t*const _EGmSlb = EGmemSlabGetSlab(slab);\
+ EGmemSlabPool_t*const _EGPlRf = _EGmSlb->control.pool;\
+ const size_t _EGmSlb_esz = _EGmSlb->control.elem_sz;\
+ const size_t _EGmSlb_ne = _EGmSlb->control.next;\
+ const size_t _EGmSlb_nn = _EGmSlb->next_list[_EGmSlb_ne];\
+ void*const _EGelem = (void*)(_EGmSlb_ne*_EGmSlb_esz + _EGmSlb->control.base);\
+ /* now update the slab */\
+ _EGmSlb->control.n_elem++;\
+ _EGmSlb->control.next = _EGmSlb_nn;\
+ EXITL(EG_SLAB_DEBUG,_EGmSlb_ne == EG_SLAB_ENDMARK, "Allocating from full slab");\
+ /* if the slab is full, move it to full list */\
+ if(_EGmSlb_nn == EG_SLAB_ENDMARK){\
+ EGeListMoveAfter(&(_EGmSlb->control.slab_cn),&(_EGPlRf->full));}\
+ /* if the slab is first-time used, move to half list */\
+ else if(_EGmSlb->control.n_elem == 1U){\
+ EGeListMoveAfter(&(_EGmSlb->control.slab_cn),&(_EGPlRf->half));}\
+ /* return the element */\
+ _EGelem;})
+
+/* ========================================================================= */
+/** @brief Given an used object within a slab, give it back to the slab for
+ * future use.
+ * @param __ptr pointer to the element to be given back to its containing slab.
+ * */
+#define EGmemSlabPushElement(__ptr) do{\
+ char*const _EGmsbPtr = (char*)(__ptr);\
+ EGmemSlab_t*const _EGmSlb = EGmemSlabGetSlab(_EGmsbPtr);\
+ EGmemSlabPool_t*const _EGPlRf = _EGmSlb->control.pool;\
+ __EGmspLock(_EGPlRf);{\
+ const size_t _EGmSlb_esz = _EGmSlb->control.elem_sz;\
+ const size_t _EGmSlb_ne = _EGmSlb->control.next;\
+ const size_t _EGmSlb_nn = ((_EGmsbPtr) - _EGmSlb->control.base)/_EGmSlb_esz;\
+ /* if debugging, check for poison in the pointer to the next element in the \
+ * given element */\
+ EXITL(EG_SLAB_DEBUG, !_EGmSlb->control.n_elem, "freeing from an empty slab");\
+ /* now actually put the element into the slab */\
+ _EGmSlb->control.n_elem--;\
+ _EGmSlb->control.next = _EGmSlb_nn;\
+ _EGmSlb->next_list[_EGmSlb_nn] = _EGmSlb_ne;\
+ __EGmsbUPD2(_EGPlRf);\
+ /* if the slab is now not being used, update accordingly */\
+ if(_EGmSlb_ne == EG_SLAB_ENDMARK){\
+ EGeListMoveAfter(&(_EGmSlb->control.slab_cn),&(_EGPlRf->half));}\
+ else if(!_EGmSlb->control.n_elem){\
+ if(_EGPlRf->freefree){\
+ EGmemSlabClear(_EGmSlb);\
+ free((void*)_EGmSlb);}\
+ else{\
+ EGeListMoveAfter(&(_EGmSlb->control.slab_cn),&(_EGPlRf->empty));}}}\
+ __EGmspUnlock(_EGPlRf);\
+ }while(0)
+
+/* ========================================================================= */
+/** @brief initialize a slab pool as an empty pool for elements of the given
+ * size, and with te given constructor and destructors.
+ * @param constr_fn constructor fnctioin for the elements to be stored in the
+ * pool.
+ * @param dest_fn destructor function for the elements to be stored in the
+ * pool.
+ * @param pool pointer to the slab pool to initialize.
+ * @param sz (real) size (in bytes) of the elements to be hold. in the pool.
+ * This means that sz is the result of sizeof(TYPE), where TYPE is the
+ * structure to be pooled. */
+#define EGmemSlabPoolInit(pool, sz, constr_fn, dest_fn) \
+ __EGmemSlabPoolInit(pool, sz, constr_fn, dest_fn, \
+ __FILE__, __func__, __LINE__)
+void __EGmemSlabPoolInit( EGmemSlabPool_t*const pool,
+ const size_t sz,
+ EGconstructor_f constr_fn,
+ EGdestructor_f dest_fn,
+ const char*const file,
+ const char*const func,
+ const int line);
+/* ========================================================================= */
+/** @brief clear a slab pool and all internal sub-structures and data, no
+ * further calls to this structure are posible after this (but for freeing the
+ * memory containing this data, or to re-initialize it).
+ * @param __Pool slab pool to be cleared.
+ * */
+void EGmemSlabPoolClear(EGmemSlabPool_t*const __Pool);
+/* ========================================================================= */
+/** @brief add one to the given pointer, if profiling is enabled, otherwise, do
+ * nothing */
+#if EG_SLAB_PROFILE <= DEBUG
+#define __EGmsbUPD1(__pool) do{\
+ __pool->ncals++;\
+ __pool->n_tot++;\
+ if(__pool->max_tot < __pool->n_tot) __pool->max_tot = __pool->n_tot;}while(0)
+#define __EGmsbUPD2(__pool) __pool->n_tot--
+#else
+#define __EGmsbUPD1(__pool)
+#define __EGmsbUPD2(__pool)
+#endif
+
+/* ========================================================================= */
+/** @brief Given a slab pool, return an element from the pool.
+ * @param __Pool slab pool from where we will get the memory.
+ * @return pointer to an initialize element. */
+#if EG_SLAB_REDUCE_TO_MALLOC
+#define EGmemSlabPoolAlloc(__Pool) ({\
+ EGmemSlabPool_t*const _EGmPl = (__Pool);\
+ void*_EGmb = EGmalloc(_EGmPl->elem_sz+sizeof(void*));\
+ void**_EGpt = (void**)_EGmb;\
+ __EGmsbUPD1(_EGmPl);\
+ (*_EGpt) = _EGmPl;\
+ _EGmb=((void*)(_EGpt+1));\
+ if(_EGmPl->constr) _EGmPl->constr(_EGmb);\
+ _EGmb;})
+#else
+#define EGmemSlabPoolAlloc(__Pool) ({\
+ EGmemSlabPool_t*const _EGmPl = (__Pool);\
+ void* _EGSmbRf = 0;\
+ void* _EGrptr = 0;\
+ int __EGmPlerr=0;\
+ __EGmspLock(_EGmPl);\
+ __EGmsbUPD1(_EGmPl);\
+ if(!EGeListIsEmpty(&(_EGmPl->half))){ _EGSmbRf = _EGmPl->half.next;}\
+ else if(!EGeListIsEmpty(&(_EGmPl->empty))){ _EGSmbRf = _EGmPl->empty.next;}\
+ else{\
+ if((__EGmPlerr=posix_memalign(&_EGSmbRf,EG_SLAB_SIZE,EG_SLAB_SIZE))){\
+ EXIT(1,"posix_memalign falied with code %d, error %s",__EGmPlerr,\
+ strerror(__EGmPlerr));}\
+ __EGmemSlabInit(_EGSmbRf,_EGmPl);}\
+ _EGrptr = EGmemSlabPopElement(_EGSmbRf);\
+ MESSAGE(EG_SLAB_VERBOSE,"Returning %p",_EGrptr);\
+ __EGmspUnlock(_EGmPl);\
+ _EGrptr;})
+#endif
+
+/* ========================================================================= */
+/** @brief Given a pointer to an element allocated through a slab pool, give it
+ * back to the pool.
+ * @param __ptr pointer to be returned to the pool.
+ * */
+#if EG_SLAB_REDUCE_TO_MALLOC
+#define EGmemSlabPoolFree(__ptr) ({\
+ void**_EGptr = ((void**)(__ptr))-1;\
+ EGmemSlabPool_t*const _EGmPl = (EGmemSlabPool_t*)(*_EGptr);\
+ __EGmsbUPD2(_EGmPl);\
+ if(_EGmPl->dest) _EGmPl->dest(((void*)(_EGptr+1)));\
+ EGfree(_EGptr);})
+#else
+#define EGmemSlabPoolFree(__ptr) EGmemSlabPushElement(__ptr)
+#endif
+
+/* ========================================================================= */
+/** @brief Given a slab pool, free all unused slabs
+ * @param pool slab pool to be shrinked. */
+void EGmemSlabPoolShrink(EGmemSlabPool_t*const pool);
+
+/* ========================================================================= */
+/** @brief set parameters for a slab pool */
+int EGmemSlabPoolSetParam(EGmemSlabPool_t*const pool,
+ const int param,
+ const int val);
+/* ========================================================================= */
+/** @brief short names for common functions */
+#define EGmsAlloc EGmemSlabPoolAlloc
+#define EGmsFree EGmemSlabPoolFree
+#define EGmsInit EGmemSlabPoolInit
+#define EGmsClear EGmemSlabPoolClear
+#define EGms_t EGmemSlabPool_t
+#define EGmsShrink EGmemSlabPoolShrink
+/* ========================================================================= */
+/* end of eg_memslab.h */
+/** @} */
+#endif
diff --git a/qsopt_ex/eg_nummacros.h b/qsopt_ex/eg_nummacros.h
new file mode 100644
index 0000000..2c74d03
--- /dev/null
+++ b/qsopt_ex/eg_nummacros.h
@@ -0,0 +1,81 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ *
+ * 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
+ * */
+#ifndef __EG_NUMMACROS_H__
+#define __EG_NUMMACROS_H__
+
+#include "eg_macros.h"
+
+/* ========================================================================= */
+/** @defgroup EGlpNumMacros General Number Utilities
+ * Here we put some utilities common for number.
+ *
+ * @par History:
+ * Revision 0.0.2
+ * - 2007-10-08
+ * - Move EGabs, EGswap, EGmin and EGmax to this file
+ * */
+/** @{*/
+/** @file
+ * @brief This file provide the user interface and function definitions
+ * for general number utilities.
+ * */
+
+/* ========================================================================= */
+/** @brief Given tree numbers N1, N2 and Ntmp, swap values of N1 and N2 using
+ * Ntmp as a temporal number. The variables should be of some primitive type of
+ * C for this macro to work.
+ * @param N1 first number.
+ * @param N2 second number.
+ * @param Ntmp temporal variable.
+ * */
+#define EGswap(N1,N2,Ntmp) do{\
+ Ntmp = N1;\
+ N1 = N2;\
+ N2 = Ntmp;} while(0)
+
+/* ========================================================================= */
+/** @brief given two variables (of the same type, and of some predefined type)
+ * return the maximum value among the two of them. */
+#define EGmax(a,b) ({\
+ const typeof(a) __EGma = (a);\
+ const typeof(b) __EGmb = (b);\
+ (__EGma > __EGmb ? __EGma : __EGmb);})
+
+/* ========================================================================= */
+/** @brief given two variables (of the same type, and of some predefined type)
+ * return the minimum value among the two of them. */
+#define EGmin(a,b) ({\
+ const typeof(a) __EGma = (a);\
+ const typeof(b) __EGmb = (b);\
+ (__EGma < __EGmb ? __EGma : __EGmb);})
+
+/* ========================================================================= */
+/** @brief a general macro to return the absolute value of the given variable
+ * @param var variable whose absolute value we want to compute.
+ * @return value of the absolute value of the given variable, note that this
+ * macro will only work in built-in types, and will use the default comparison
+ * for those internal types. */
+#define EGabs(var) ({\
+ const typeof(var) __EGav = (var);\
+ (__EGav < 0) ? -__EGav : __EGav;})
+
+/* ========================================================================= */
+/** @}*/
+#endif
diff --git a/qsopt_ex/eg_numutil.c b/qsopt_ex/eg_numutil.c
new file mode 100644
index 0000000..7a0ef95
--- /dev/null
+++ b/qsopt_ex/eg_numutil.c
@@ -0,0 +1,106 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ *
+ * 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
+ * */
+#include "eg_numutil_EGLPNUM_TYPENAME.h"
+/** @file
+ * @ingroup EGlpNumUtil */
+/** @addtogroup EGlpNumUtil */
+/** @{ */
+/* ========================================================================= */
+void EGLPNUM_TYPENAME_EGutilPermSort (const size_t sz,
+ int *const perm,
+ const EGLPNUM_TYPE * const elem)
+{
+ size_t i,
+ j;
+ int temp;
+ EGLPNUM_TYPE t;
+ if (sz <= 1)
+ return;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (t);
+ EGswap (perm[0], perm[(sz - 1) / 2], temp);
+ i = 0;
+ j = sz;
+ EGLPNUM_TYPENAME_EGlpNumCopy (t, elem[perm[0]]);
+ for (;;)
+ {
+ do
+ i++;
+ while (i < sz && EGLPNUM_TYPENAME_EGlpNumIsLess (elem[perm[i]], t));
+ do
+ j--;
+ while (j && EGLPNUM_TYPENAME_EGlpNumIsLess (t, elem[perm[j]]));
+ if (j < i)
+ break;
+ EGswap (perm[i], perm[j], temp);
+ }
+ EGswap (perm[0], perm[j], temp);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (t);
+ EGLPNUM_TYPENAME_EGutilPermSort (j, perm, elem);
+ EGLPNUM_TYPENAME_EGutilPermSort (sz - i, perm + i, elem);
+}
+
+/* ========================================================================= */
+void EGLPNUM_TYPENAME_EGutilPermSort2 (const size_t sz,
+ int *const perm,
+ const EGLPNUM_TYPE * const elem)
+{
+ size_t i,
+ j;
+ int temp;
+ EGLPNUM_TYPE t;
+ if (sz <= 1)
+ return;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (t);
+ EGswap (perm[0], perm[(sz - 1) / 2], temp);
+ i = 0;
+ j = sz;
+ EGLPNUM_TYPENAME_EGlpNumCopy (t, elem[perm[0]]);
+ for (;;)
+ {
+ do
+ i++;
+ while (i < sz && EGLPNUM_TYPENAME_EGlpNumIsLess (t, elem[perm[i]]));
+ do
+ j--;
+ while (EGLPNUM_TYPENAME_EGlpNumIsLess (elem[perm[j]], t));
+ if (j < i)
+ break;
+ EGswap (perm[i], perm[j], temp);
+ }
+ EGswap (perm[0], perm[j], temp);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (t);
+ EGLPNUM_TYPENAME_EGutilPermSort2 (j, perm, elem);
+ EGLPNUM_TYPENAME_EGutilPermSort2 (sz - i, perm + i, elem);
+}
+
+/* ========================================================================= */
+void EGLPNUM_TYPENAME___EGlpNumInnProd(EGLPNUM_TYPE*rop,
+ EGLPNUM_TYPE*const __EGa1,
+ EGLPNUM_TYPE*const __EGa2,
+ const size_t length )
+{
+ size_t __EGdim = length;
+ EGLPNUM_TYPENAME_EGlpNumZero((*rop));
+ while(__EGdim--) EGLPNUM_TYPENAME_EGlpNumAddInnProdTo((*rop),__EGa1[__EGdim],__EGa2[__EGdim]);
+}
+/* ========================================================================= */
+/** @} */
diff --git a/qsopt_ex/eg_numutil.h b/qsopt_ex/eg_numutil.h
new file mode 100644
index 0000000..f35b663
--- /dev/null
+++ b/qsopt_ex/eg_numutil.h
@@ -0,0 +1,97 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ *
+ * 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
+ * */
+#ifndef EGLPNUM_TYPENAME___EG_NUMUTIL_H__
+#define EGLPNUM_TYPENAME___EG_NUMUTIL_H__
+
+#include "eg_macros.h"
+#include "eg_nummacros.h"
+#include "eg_lpnum.h"
+
+/* ========================================================================= */
+/** @defgroup EGlpNumUtil General Number Utilities
+ * Here we put some utilities common for different number types but thaat we
+ * want to implement as templates, like permutation sorting, inner product of
+ * vectors, and so-on..
+ *
+ * @par History:
+ * Revision 0.0.2
+ * - 2007-10-08
+ * - Separate template file and independet file into eg_nummacros.h
+ * - Move EGabs, EGswap, EGmin and EGmax to this file
+ * - 2005-10-31
+ * - First implementation.
+ * */
+/** @{*/
+/** @file
+ * @brief This file provide the user interface and function definitions for
+ * general number utilities.
+ * */
+
+/* Swap two EGLPNUM_TYPE variables using the third as a temporary. */
+#define EGLPNUM_TYPENAME_EGLPNUM_SWAP(a,b,t) ((EGLPNUM_TYPENAME_EGlpNumCopy(t,a)),(EGLPNUM_TYPENAME_EGlpNumCopy(a,b)),(EGLPNUM_TYPENAME_EGlpNumCopy(b,t)))
+
+/* ========================================================================= */
+/** @brief compute the inner product of two arrays.
+ * @param arr1 first array.
+ * @param arr2 second array.
+ * @param length number of entries to consider in both arrays, from zero to
+ * length - 1.
+ * @param rop where to store the result.
+ * */
+#define EGLPNUM_TYPENAME_EGlpNumInnProd(__rop,__arr1,__arr2,__length) EGLPNUM_TYPENAME___EGlpNumInnProd((&(__rop)),__arr1,__arr2,__length)
+/* ========================================================================= */
+/** @brief internal version, this is done to avoid using stdc99 and rely on
+ * more basic stdc89 */
+void EGLPNUM_TYPENAME___EGlpNumInnProd(EGLPNUM_TYPE*rop,EGLPNUM_TYPE*const arr1,EGLPNUM_TYPE*const arr2, const size_t length);
+/* ========================================================================= */
+/** @brief Sort (in increasing order) a sub-set of entries in an array using
+ * quicksort, by permutating the order of the elements in the subset rather
+ * than in the whole original array.
+ * @param sz length of the permutation array.
+ * @param perm array of indices of elements that we want to sort.
+ * @param elem array (of length at least max(perm[k]:k=0,...,sz-1)) containing
+ * the elements to be sorted.
+ * @note The array of elements is not changed by this function.
+ * @note This code is based in concorde's implementation of
+ * permutation-quick-sort.
+ * */
+void EGLPNUM_TYPENAME_EGutilPermSort (const size_t sz,
+ int *const perm,
+ const EGLPNUM_TYPE * const elem);
+
+/* ========================================================================= */
+/** @brief Sort (in decreasing order) a sub-set of entries in an array using
+ * quicksort, by permutating the order of the elements in the subset rather
+ * than in the whole original array.
+ * @param sz length of the permutation array.
+ * @param perm array of indices of elements that we want to sort.
+ * @param elem array (of length at least max(perm[k]:k=0,...,sz-1)) containing
+ * the elements to be sorted.
+ * @note The array of elements is not changed by this function.
+ * @note This code is based in concorde's implementation of
+ * permutation-quick-sort.
+ * */
+void EGLPNUM_TYPENAME_EGutilPermSort2 (const size_t sz,
+ int*const perm,
+ const EGLPNUM_TYPE*const elem);
+
+/* ========================================================================= */
+/** @}*/
+#endif
diff --git a/qsopt_ex/eg_timer.h b/qsopt_ex/eg_timer.h
new file mode 100644
index 0000000..1e1b56f
--- /dev/null
+++ b/qsopt_ex/eg_timer.h
@@ -0,0 +1,143 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ *
+ * 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
+ * */
+/* ========================================================================= */
+/** @defgroup EGtimer EGtimer
+ *
+ * Here we implement types and functions for __timer functions
+ *
+ * @version 1.0.1
+ * @par History:
+ * - 2013-04-18
+ * - Add EGtimerZero static initializer
+ * - 2006-01-25
+ * - Fix compilation errors on sun, change includes accordingly and
+ * code
+ * - 2005-05-31
+ * - Eliminate the definition of #EGwallClockTimer_t and replace it by
+ * a macro definition that replace it by #EGtimer_t.
+ * - 2004-01-20
+ * - Add a 'wall clock' __timer (Renan-Marcos) type and functions
+ * - 2003-05-08
+ * - First Implementation
+ * @note Up to now, this code will only work on linux machines, and maybe on
+ * unix/posix systems.
+ * */
+/** @file
+ * @ingroup EGtimer */
+/** @addtogroup EGtimer */
+/** @{ */
+/* ========================================================================= */
+
+#ifndef __EG_TIMER_H__
+#define __EG_TIMER_H__
+
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include "eg_macros.h"
+
+/* ========================================================================= */
+/** @brief Get system time.
+ *
+ * This function is for internal purposes only and should not be called from the
+ * user space, it ask the (user) time from the system.
+ * @return the time (in seconds) stored as a double. */
+#ifdef HAVE_GETRUSAGE
+#define __EGzeit() ({\
+ struct rusage __EGzeit_ru;\
+ int __EGzeit_st = getrusage(RUSAGE_SELF,&__EGzeit_ru);\
+ EXIT(__EGzeit_st,"getrusage failed with code error %d (%s)", errno, \
+ strerror(errno));\
+ (((double)__EGzeit_ru.ru_utime.tv_sec) + \
+ ((double)__EGzeit_ru.ru_utime.tv_usec)/1000000);})
+#else
+#ifdef HAVE_TIMES
+#ifdef CLK_TCK
+#define MACHINE_FREQ CLK_TCK
+#else
+#define MACHINE_FREQ HZ
+#endif
+#define __EGzeit() ({\
+ struct tms __EGzeit_now;\
+ times(&__EGzeit_now);\
+ ((double) __EGzeit_now.tms_utime)/((double) MACHINE_FREQ);})
+#else
+#error Your system does not have (or the configure script could not find)\
+ getrusage nor times functions, and thus we are unable to provide \
+ timing functions. Without them this library will not compile in this system
+#endif
+#endif
+
+/* ========================================================================= */
+/** @brief this structure holds a __timer structure */
+typedef struct
+{
+ double time; /**< hold the accumulated time */
+ double stime; /**< hols the last time when we start counting, this is only
+ for internal purposes, the user should only use the
+ field 'time' */
+}
+EGtimer_t;
+/* ========================================================================= */
+/** @brief static initializer */
+#define EGtimerZero {.time=0,.stime=0}
+/* ========================================================================= */
+/** @brief This is done for backward compability, we used to define
+ * EGwallClockTimer_t just as the normal __timer, so in reality we don't need
+ * another type, but keep the name so that older code depending on this still
+ * compiles. */
+#define EGwallClockTimer_t EGtimer_t
+
+/* ========================================================================= */
+/** @brief Set a new starting time for the __timer.
+ * @param __timer pointer to a EGtimer_t structure.
+ * @return starting time (in seconds), and the type is a double. */
+#define EGtimerStart(__timer) ({(__timer)->stime = __EGzeit();})
+
+/* ========================================================================= */
+/** @brief Stop a 'running' __timer and accumulate the run time.
+ * @return the time elapsed since the last 'start' call (in seconds). */
+#define EGtimerStop(__timer) ({(__timer)->time += __EGzeit() - (__timer)->stime;})
+
+/* ========================================================================= */
+/** @brief this function reset the accumulated time to zero */
+#define EGtimerReset(__timer) ({(__timer)->time = 0;})
+
+/* ========================================================================= */
+/** @brief Set the starting time the current (wall) time.
+ * @return the current wall time. */
+#define EGwallClockTimerStart(__timer) ({(__timer)->stime = time(0);})
+
+/* ========================================================================= */
+/** @brief Stop a 'running' __timer and accumulate the (wall) runing time.
+ * @return the wall time elapsed since the last initialization. */
+#define EGwallClockTimerStop(__timer) ({\
+ (__timer)->time += difftime(time(0),(__timer)->stime);})
+
+/* ========================================================================= */
+/** @brief Reset the accumulated time to zero */
+#define EGwallClockTimerReset(__timer) EGtimerReset(__timer)
+
+/* ========================================================================= */
+/** @}
+ * end of eg_timer.h */
+#endif
diff --git a/qsopt_ex/exact.c b/qsopt_ex/exact.c
new file mode 100644
index 0000000..4fbdd0a
--- /dev/null
+++ b/qsopt_ex/exact.c
@@ -0,0 +1,1824 @@
+/* ========================================================================= */
+/* ESolver "Exact Mixed Integer Linear Solver" provides some basic structures
+ * and algorithms commons in solving MIP's
+ *
+ * Copyright (C) 2005 Daniel Espinoza.
+ *
+ * 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
+ * */
+/* ========================================================================= */
+/** @file
+ * @ingroup Esolver */
+/** @addtogroup Esolver */
+/** @{ */
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "exact.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "logging-private.h"
+
+#include "util.h"
+#include "eg_timer.h"
+#include "eg_exutil.h"
+#include "except.h"
+
+#include "basis_mpq.h"
+#include "editor_dbl.h"
+#include "editor_mpf.h"
+#include "fct_mpq.h"
+#include "lpdata_mpq.h"
+#include "simplex_mpq.h"
+
+/* ========================================================================= */
+int QSexact_print_sol (mpq_QSdata * p,
+ EGioFile_t * out_f)
+{
+ int rval = 0,
+ status;
+ const int ncols = mpq_QSget_colcount (p);
+ const int nrows = mpq_QSget_rowcount (p);
+ mpq_t *x = mpq_EGlpNumAllocArray (ncols);
+ mpq_t *rc = mpq_EGlpNumAllocArray (ncols);
+ mpq_t *slack = mpq_EGlpNumAllocArray (nrows);
+ mpq_t *pi = mpq_EGlpNumAllocArray (nrows);
+ mpq_t value;
+ register int i;
+ char *str1 = 0;
+ mpq_init (value);
+ EGcallD(mpq_QSget_status (p, &status));
+ if(mpq_QSget_x_array (p, x)) mpq_EGlpNumFreeArray (x);
+ if(mpq_QSget_slack_array (p, slack)) mpq_EGlpNumFreeArray (slack);
+ if(mpq_QSget_pi_array (p, pi)) mpq_EGlpNumFreeArray (pi);
+ if(mpq_QSget_rc_array (p, rc)) mpq_EGlpNumFreeArray (rc);
+
+ switch (status)
+ {
+ case QS_LP_OPTIMAL:
+ EGcallD(mpq_QSget_objval (p, &value));
+ str1 = mpq_EGlpNumGetStr (value);
+ EGioPrintf (out_f, "status OPTIMAL\n\tValue = %s\n", str1);
+ free (str1);
+ str1 = 0;
+ break;
+ case QS_LP_INFEASIBLE:
+ EGioPrintf (out_f, "status INFEASIBLE\n");
+ break;
+ case QS_LP_UNBOUNDED:
+ EGioPrintf (out_f, "status UNBOUNDED\n");
+ break;
+ case QS_LP_ITER_LIMIT:
+ case QS_LP_TIME_LIMIT:
+ case QS_LP_UNSOLVED:
+ case QS_LP_ABORTED:
+ case QS_LP_MODIFIED:
+ EGioPrintf (out_f, "status NOT_SOLVED\n");
+ break;
+ }
+ if (x)
+ {
+ EGioPrintf (out_f, "VARS:\n");
+ for (i = 0; i < ncols; i++)
+ if (!mpq_equal (x[i], __zeroLpNum_mpq__))
+ {
+ str1 = mpq_EGlpNumGetStr (x[i]);
+ EGioPrintf (out_f, "%s = %s\n", p->qslp->colnames[i], str1);
+ free (str1);
+ }
+ }
+ if (rc)
+ {
+ EGioPrintf (out_f, "REDUCED COST:\n");
+ for (i = 0; i < ncols; i++)
+ if (!mpq_equal (rc[i], __zeroLpNum_mpq__))
+ {
+ str1 = mpq_EGlpNumGetStr (rc[i]);
+ EGioPrintf (out_f, "%s = %s\n", p->qslp->colnames[i], str1);
+ free (str1);
+ }
+ }
+ if (pi)
+ {
+ EGioPrintf (out_f, "PI:\n");
+ for (i = 0; i < nrows; i++)
+ if (!mpq_equal (pi[i], __zeroLpNum_mpq__))
+ {
+ str1 = mpq_EGlpNumGetStr (pi[i]);
+ EGioPrintf (out_f, "%s = %s\n", p->qslp->rownames[i], str1);
+ free (str1);
+ }
+ }
+ if (slack)
+ {
+ EGioPrintf (out_f, "SLACK:\n");
+ for (i = 0; i < nrows; i++)
+ if (!mpq_equal (slack[i], __zeroLpNum_mpq__))
+ {
+ str1 = mpq_EGlpNumGetStr (slack[i]);
+ EGioPrintf (out_f, "%s = %s\n", p->qslp->rownames[i], str1);
+ free (str1);
+ }
+ }
+
+ /* ending */
+CLEANUP:
+ if (x)
+ mpq_EGlpNumFreeArray (x);
+ if (pi)
+ mpq_EGlpNumFreeArray (pi);
+ if (rc)
+ mpq_EGlpNumFreeArray (rc);
+ if (slack)
+ mpq_EGlpNumFreeArray (slack);
+ mpq_clear (value);
+ return rval;
+}
+
+/* ========================================================================= */
+dbl_QSdata *QScopy_prob_mpq_dbl (mpq_QSdata * p,
+ const char *newname)
+{
+ const int ncol = mpq_QSget_colcount(p);
+ const int nrow = mpq_QSget_rowcount(p);
+ char*sense=0;
+ int*rowcnt=0;
+ int*rowbeg=0;
+ int*rowind=0;
+ int objsense;
+ mpq_t*mpq_lb=0;
+ mpq_t*mpq_ub=0;
+ mpq_t*mpq_obj=0;
+ mpq_t*mpq_range=0;
+ mpq_t*mpq_rhs=0;
+ mpq_t*mpq_rowval=0;
+ double*dbl_lb=0;
+ double*dbl_ub=0;
+ double*dbl_obj=0;
+ double*dbl_range=0;
+ double*dbl_rhs=0;
+ double*dbl_rowval=0;
+ dbl_QSdata *p2 = 0;
+ int rval = 0;
+ register int i;
+ mpq_t mpq_val;
+ double dbl_val;
+ mpq_init(mpq_val);
+ /* get all information */
+ EGcallD(mpq_QSget_objsense(p,&objsense));
+ mpq_lb = mpq_EGlpNumAllocArray(ncol);
+ mpq_ub = mpq_EGlpNumAllocArray(ncol);
+ EGcallD(mpq_QSget_bounds(p,mpq_lb,mpq_ub));
+ dbl_lb = QScopy_array_mpq_dbl(mpq_lb);
+ dbl_ub = QScopy_array_mpq_dbl(mpq_ub);
+ mpq_EGlpNumFreeArray(mpq_ub);
+ mpq_obj = mpq_lb;
+ mpq_lb = 0;
+ EGcallD(mpq_QSget_obj(p, mpq_obj));
+ dbl_obj = QScopy_array_mpq_dbl(mpq_obj);
+ mpq_EGlpNumFreeArray(mpq_obj);
+ EGcallD(mpq_QSget_ranged_rows(p, &rowcnt, &rowbeg, &rowind, &mpq_rowval,
+ &mpq_rhs, &sense, &mpq_range, 0));
+ dbl_rowval = QScopy_array_mpq_dbl(mpq_rowval);
+ mpq_EGlpNumFreeArray(mpq_rowval);
+ dbl_range = QScopy_array_mpq_dbl(mpq_range);
+ mpq_EGlpNumFreeArray(mpq_range);
+ dbl_rhs = QScopy_array_mpq_dbl(mpq_rhs);
+ mpq_EGlpNumFreeArray(mpq_rhs);
+ /* create copy */
+ p2 = dbl_QScreate_prob (newname, objsense);
+ if (!p2) goto CLEANUP;
+ for( i = 0 ; i < ncol; i++)
+ {
+ EGcallD(dbl_QSnew_col(p2, dbl_obj[i], dbl_lb[i], dbl_ub[i], 0));
+ }
+ dbl_EGlpNumFreeArray(dbl_lb);
+ dbl_EGlpNumFreeArray(dbl_ub);
+ dbl_EGlpNumFreeArray(dbl_obj);
+ EGcallD(dbl_QSadd_ranged_rows(p2, nrow, rowcnt, rowbeg, rowind,
+ dbl_rowval, dbl_rhs, sense, dbl_range, 0));
+ /* set parameters */
+ EGcallD(mpq_QSget_param(p, QS_PARAM_PRIMAL_PRICING, &objsense));
+ EGcallD(dbl_QSset_param(p2, QS_PARAM_PRIMAL_PRICING, objsense));
+ EGcallD(mpq_QSget_param(p, QS_PARAM_DUAL_PRICING, &objsense));
+ EGcallD(dbl_QSset_param(p2, QS_PARAM_DUAL_PRICING, objsense));
+ EGcallD(mpq_QSget_param(p, QS_PARAM_SIMPLEX_DISPLAY, &objsense));
+ EGcallD(dbl_QSset_param(p2, QS_PARAM_SIMPLEX_DISPLAY, objsense));
+ EGcallD(mpq_QSget_param(p, QS_PARAM_SIMPLEX_MAX_ITERATIONS, &objsense));
+ EGcallD(dbl_QSset_param(p2, QS_PARAM_SIMPLEX_MAX_ITERATIONS, objsense));
+ EGcallD(mpq_QSget_param(p, QS_PARAM_SIMPLEX_SCALING, &objsense));
+ EGcallD(dbl_QSset_param(p2, QS_PARAM_SIMPLEX_SCALING, objsense));
+ EGcallD(mpq_QSget_param_EGlpNum(p, QS_PARAM_SIMPLEX_MAX_TIME, &mpq_val));
+ dbl_val = mpq_get_d(mpq_val);
+ EGcallD(dbl_QSset_param_EGlpNum(p2, QS_PARAM_SIMPLEX_MAX_TIME, dbl_val));
+ EGcallD(mpq_QSget_param_EGlpNum(p, QS_PARAM_OBJULIM, &mpq_val));
+ dbl_val = mpq_get_d(mpq_val);
+ EGcallD(dbl_QSset_param_EGlpNum(p2, QS_PARAM_OBJULIM, dbl_val));
+ EGcallD(mpq_QSget_param_EGlpNum(p, QS_PARAM_OBJLLIM, &mpq_val));
+ dbl_val = mpq_get_d(mpq_val);
+ EGcallD(dbl_QSset_param_EGlpNum(p2, QS_PARAM_OBJLLIM, dbl_val));
+ /* ending */
+ CLEANUP:
+ mpq_clear(mpq_val);
+ dbl_EGlpNumFreeArray(dbl_rowval);
+ dbl_EGlpNumFreeArray(dbl_range);
+ dbl_EGlpNumFreeArray(dbl_rhs);
+ dbl_EGlpNumFreeArray(dbl_lb);
+ dbl_EGlpNumFreeArray(dbl_ub);
+ dbl_EGlpNumFreeArray(dbl_obj);
+ mpq_EGlpNumFreeArray(mpq_rowval);
+ mpq_EGlpNumFreeArray(mpq_range);
+ mpq_EGlpNumFreeArray(mpq_rhs);
+ mpq_EGlpNumFreeArray(mpq_lb);
+ mpq_EGlpNumFreeArray(mpq_ub);
+ mpq_EGlpNumFreeArray(mpq_obj);
+ EGfree(rowcnt);
+ EGfree(rowbeg);
+ EGfree(rowind);
+ EGfree(sense);
+ if (rval)
+ {
+ dbl_QSfree_prob (p2);
+ p2 = 0;
+ }
+#if QSEXACT_SAVE_INT
+ else
+ {
+ dbl_QSwrite_prob (p2, "prob.dbl.lp", "LP");
+ }
+#endif
+ return p2;
+}
+
+/* ========================================================================= */
+mpf_QSdata *QScopy_prob_mpq_mpf (mpq_QSdata * p,
+ const char *newname)
+{
+ const int ncol = mpq_QSget_colcount(p);
+ const int nrow = mpq_QSget_rowcount(p);
+ char*sense=0;
+ int*rowcnt=0;
+ int*rowbeg=0;
+ int*rowind=0;
+ int objsense;
+ mpq_t*mpq_lb=0;
+ mpq_t*mpq_ub=0;
+ mpq_t*mpq_obj=0;
+ mpq_t*mpq_range=0;
+ mpq_t*mpq_rhs=0;
+ mpq_t*mpq_rowval=0;
+ mpf_t*mpf_lb=0;
+ mpf_t*mpf_ub=0;
+ mpf_t*mpf_obj=0;
+ mpf_t*mpf_range=0;
+ mpf_t*mpf_rhs=0;
+ mpf_t*mpf_rowval=0;
+ mpf_QSdata *p2 = 0;
+ int rval = 0;
+ mpq_t mpq_val;
+ mpf_t mpf_val;
+ register int i;
+ mpq_init(mpq_val);
+ mpf_init(mpf_val);
+ /* get all information */
+ EGcallD(mpq_QSget_objsense(p,&objsense));
+ mpq_lb = mpq_EGlpNumAllocArray(ncol);
+ mpq_ub = mpq_EGlpNumAllocArray(ncol);
+ EGcallD(mpq_QSget_bounds(p,mpq_lb,mpq_ub));
+ mpf_lb = QScopy_array_mpq_mpf(mpq_lb);
+ mpf_ub = QScopy_array_mpq_mpf(mpq_ub);
+ mpq_EGlpNumFreeArray(mpq_ub);
+ mpq_obj = mpq_lb;
+ mpq_lb = 0;
+ EGcallD(mpq_QSget_obj(p, mpq_obj));
+ mpf_obj = QScopy_array_mpq_mpf(mpq_obj);
+ mpq_EGlpNumFreeArray(mpq_obj);
+ EGcallD(mpq_QSget_ranged_rows(p, &rowcnt, &rowbeg, &rowind, &mpq_rowval, &mpq_rhs, &sense, &mpq_range, 0));
+ mpf_rowval = QScopy_array_mpq_mpf(mpq_rowval);
+ mpq_EGlpNumFreeArray(mpq_rowval);
+ mpf_range = QScopy_array_mpq_mpf(mpq_range);
+ mpq_EGlpNumFreeArray(mpq_range);
+ mpf_rhs = QScopy_array_mpq_mpf(mpq_rhs);
+ mpq_EGlpNumFreeArray(mpq_rhs);
+ /* create copy */
+ p2 = mpf_QScreate_prob (newname, objsense);
+ if (!p2) goto CLEANUP;
+ for( i = 0 ; i < ncol; i++)
+ {
+ EGcallD(mpf_QSnew_col(p2, mpf_obj[i], mpf_lb[i], mpf_ub[i], 0));
+ }
+ mpf_EGlpNumFreeArray(mpf_lb);
+ mpf_EGlpNumFreeArray(mpf_ub);
+ mpf_EGlpNumFreeArray(mpf_obj);
+ EGcallD(mpf_QSadd_ranged_rows(p2, nrow, rowcnt, rowbeg, rowind, (const mpf_t*)mpf_rowval,(const mpf_t*) mpf_rhs, sense,(const mpf_t*) mpf_range, 0));
+ /* set parameters */
+ EGcallD(mpq_QSget_param(p, QS_PARAM_PRIMAL_PRICING, &objsense));
+ EGcallD(mpf_QSset_param(p2, QS_PARAM_PRIMAL_PRICING, objsense));
+ EGcallD(mpq_QSget_param(p, QS_PARAM_DUAL_PRICING, &objsense));
+ EGcallD(mpf_QSset_param(p2, QS_PARAM_DUAL_PRICING, objsense));
+ EGcallD(mpq_QSget_param(p, QS_PARAM_SIMPLEX_DISPLAY, &objsense));
+ EGcallD(mpf_QSset_param(p2, QS_PARAM_SIMPLEX_DISPLAY, objsense));
+ EGcallD(mpq_QSget_param(p, QS_PARAM_SIMPLEX_MAX_ITERATIONS, &objsense));
+ EGcallD(mpf_QSset_param(p2, QS_PARAM_SIMPLEX_MAX_ITERATIONS, objsense));
+ EGcallD(mpq_QSget_param(p, QS_PARAM_SIMPLEX_SCALING, &objsense));
+ EGcallD(mpf_QSset_param(p2, QS_PARAM_SIMPLEX_SCALING, objsense));
+ EGcallD(mpq_QSget_param_EGlpNum(p, QS_PARAM_SIMPLEX_MAX_TIME, &mpq_val));
+ mpf_set_q(mpf_val,mpq_val);
+ EGcallD(mpf_QSset_param_EGlpNum(p2, QS_PARAM_SIMPLEX_MAX_TIME, mpf_val));
+ EGcallD(mpq_QSget_param_EGlpNum(p, QS_PARAM_OBJULIM, &mpq_val));
+ mpf_set_q(mpf_val,mpq_val);
+ EGcallD(mpf_QSset_param_EGlpNum(p2, QS_PARAM_OBJULIM, mpf_val));
+ EGcallD(mpq_QSget_param_EGlpNum(p, QS_PARAM_OBJLLIM, &mpq_val));
+ mpf_set_q(mpf_val,mpq_val);
+ EGcallD(mpf_QSset_param_EGlpNum(p2, QS_PARAM_OBJLLIM, mpf_val));
+ /* ending */
+ CLEANUP:
+ mpq_clear(mpq_val);
+ mpf_clear(mpf_val);
+ mpf_EGlpNumFreeArray(mpf_rowval);
+ mpf_EGlpNumFreeArray(mpf_range);
+ mpf_EGlpNumFreeArray(mpf_rhs);
+ mpf_EGlpNumFreeArray(mpf_lb);
+ mpf_EGlpNumFreeArray(mpf_ub);
+ mpf_EGlpNumFreeArray(mpf_obj);
+ mpq_EGlpNumFreeArray(mpq_rowval);
+ mpq_EGlpNumFreeArray(mpq_range);
+ mpq_EGlpNumFreeArray(mpq_rhs);
+ mpq_EGlpNumFreeArray(mpq_lb);
+ mpq_EGlpNumFreeArray(mpq_ub);
+ mpq_EGlpNumFreeArray(mpq_obj);
+ EGfree(rowcnt);
+ EGfree(rowbeg);
+ EGfree(rowind);
+ EGfree(sense);
+ if (rval)
+ {
+ mpf_QSfree_prob (p2);
+ p2 = 0;
+ }
+#if QSEXACT_SAVE_INT
+ else
+ {
+ mpf_QSwrite_prob (p2, "prob.mpf.lp", "LP");
+ }
+#endif
+ return p2;
+}
+
+#if QSEXACT_SAVE_OPTIMAL
+/* ========================================================================= */
+/** @brief used to enumerate the generated optimal tests */
+static int QSEXACT_SAVE_OPTIMAL_IND = 0;
+#endif
+
+/* ========================================================================= */
+int QSexact_optimal_test (mpq_QSdata * p,
+ mpq_t * p_sol,
+ mpq_t * d_sol,
+ QSbasis * basis)
+{
+ /* local variables */
+ register int i,
+ j;
+ mpq_ILLlpdata *qslp = p->lp->O;
+ int *iarr1 = 0,
+ *rowmap = qslp->rowmap,
+ *structmap = qslp->structmap,
+ col;
+ mpq_t *arr1 = 0,
+ *arr2 = 0,
+ *arr3 = 0,
+ *arr4 = 0,
+ *rhs_copy = 0;
+ mpq_t *dz = 0;
+ int objsense = (qslp->objsense == QS_MIN) ? 1 : -1;
+ int const msg_lvl = __QS_SB_VERB <= DEBUG ? 0 : 100000 * (1 - p->simplex_display);
+ int rval = 1; /* store whether or not the solution is optimal, we start
+ * assuming it is. */
+ mpq_t num1,
+ num2,
+ num3,
+ p_obj,
+ d_obj;
+ mpq_init (num1);
+ mpq_init (num2);
+ mpq_init (num3);
+ mpq_init (p_obj);
+ mpq_init (d_obj);
+ mpq_set_ui (p_obj, 0UL, 1UL);
+ mpq_set_ui (d_obj, 0UL, 1UL);
+
+ /* now check if the given basis is the optimal basis */
+ arr3 = qslp->lower;
+ arr4 = qslp->upper;
+ if (mpq_QSload_basis (p, basis))
+ {
+ rval = 0;
+ MESSAGE (msg_lvl, "QSload_basis failed");
+ goto CLEANUP;
+ }
+ for (i = basis->nstruct; i--;)
+ {
+ /* check that the upper and lower bound define a non-empty space */
+ if (mpq_cmp (arr3[structmap[i]], arr4[structmap[i]]) > 0)
+ {
+ rval = 0;
+ if(!msg_lvl)
+ {
+ MESSAGE(0, "variable %s has empty feasible range [%lg,%lg]",
+ qslp->colnames[i], mpq_EGlpNumToLf(arr3[structmap[i]]),
+ mpq_EGlpNumToLf(arr4[structmap[i]]));
+ }
+ goto CLEANUP;
+ }
+ /* set the variable to its apropiate values, depending its status */
+ switch (basis->cstat[i])
+ {
+ case QS_COL_BSTAT_FREE:
+ case QS_COL_BSTAT_BASIC:
+ if (mpq_cmp (p_sol[i], arr4[structmap[i]]) > 0)
+ mpq_set (p_sol[i], arr4[structmap[i]]);
+ else if (mpq_cmp (p_sol[i], arr3[structmap[i]]) < 0)
+ mpq_set (p_sol[i], arr3[structmap[i]]);
+ break;
+ case QS_COL_BSTAT_UPPER:
+ mpq_set (p_sol[i], arr4[structmap[i]]);
+ break;
+ case QS_COL_BSTAT_LOWER:
+ mpq_set (p_sol[i], arr3[structmap[i]]);
+ break;
+ default:
+ rval = 0;
+ MESSAGE (msg_lvl, "Unknown Variable basic status %d, for variable "
+ "(%s,%d)", basis->cstat[i], qslp->colnames[i], i);
+ goto CLEANUP;
+ break;
+ }
+ }
+ for (i = basis->nrows; i--;)
+ {
+ /* check that the upper and lower bound define a non-empty space */
+ if (mpq_cmp (arr3[rowmap[i]], arr4[rowmap[i]]) > 0)
+ {
+ rval = 0;
+ if(!msg_lvl)
+ {
+ MESSAGE(0, "constraint %s logical has empty feasible range "
+ "[%lg,%lg]", qslp->rownames[i],
+ mpq_EGlpNumToLf(arr3[rowmap[i]]),
+ mpq_EGlpNumToLf(arr4[rowmap[i]]));
+ }
+ goto CLEANUP;
+ }
+ /* set the variable to its apropiate values, depending its status */
+ switch (basis->rstat[i])
+ {
+ case QS_ROW_BSTAT_BASIC:
+ if (mpq_cmp (p_sol[i + basis->nstruct], arr4[rowmap[i]]) > 0)
+ mpq_set (p_sol[i + basis->nstruct], arr4[rowmap[i]]);
+ else if (mpq_cmp (p_sol[i + basis->nstruct], arr3[rowmap[i]]) < 0)
+ mpq_set (p_sol[i + basis->nstruct], arr3[rowmap[i]]);
+ break;
+ case QS_ROW_BSTAT_UPPER:
+ mpq_set (p_sol[i + basis->nstruct], arr4[rowmap[i]]);
+ break;
+ case QS_ROW_BSTAT_LOWER:
+ mpq_set (p_sol[i + basis->nstruct], arr3[rowmap[i]]);
+ break;
+ default:
+ rval = 0;
+ MESSAGE (msg_lvl, "Unknown Variable basic status %d, for constraint "
+ "(%s,%d)", basis->cstat[i], qslp->rownames[i], i);
+ goto CLEANUP;
+ break;
+ }
+ }
+
+ /* compute the actual RHS */
+ rhs_copy = mpq_EGlpNumAllocArray (qslp->nrows);
+ for (i = qslp->nstruct; i--;)
+ {
+ if (!mpq_equal (p_sol[i], mpq_zeroLpNum))
+ {
+ arr1 = qslp->A.matval + qslp->A.matbeg[structmap[i]];
+ iarr1 = qslp->A.matind + qslp->A.matbeg[structmap[i]];
+ for (j = qslp->A.matcnt[structmap[i]]; j--;)
+ {
+ mpq_mul (num1, arr1[j], p_sol[i]);
+ mpq_add (rhs_copy[iarr1[j]], rhs_copy[iarr1[j]], num1);
+ }
+ }
+ }
+
+ /* now check if both rhs and copy_rhs are equal */
+ arr4 = qslp->upper;
+ arr1 = qslp->rhs;
+ arr2 = qslp->lower;
+ for (i = qslp->nrows; i--;)
+ {
+ mpq_mul (num1, arr1[i], d_sol[i]);
+ mpq_add (d_obj, d_obj, num1);
+ mpq_sub (num2, arr1[i], rhs_copy[i]);
+ EXIT (qslp->A.matcnt[rowmap[i]] != 1, "Imposible!");
+ if (basis->rstat[i] == QS_ROW_BSTAT_BASIC)
+ mpq_div (p_sol[qslp->nstruct + i], num2,
+ qslp->A.matval[qslp->A.matbeg[rowmap[i]]]);
+ else
+ {
+ mpq_mul (num1, p_sol[qslp->nstruct + i],
+ qslp->A.matval[qslp->A.matbeg[rowmap[i]]]);
+ if (!mpq_equal (num1, num2))
+ {
+ rval = 0;
+ if(!msg_lvl)
+ {
+ MESSAGE(0, "solution is infeasible for constraint %s, violation"
+ " %lg", qslp->rownames[i],
+ mpq_get_d (num1) - mpq_get_d (num2));
+ }
+ goto CLEANUP;
+ }
+ }
+ mpq_set (num2, p_sol[qslp->nstruct + i]);
+ /* now we check the bounds on the logical variables */
+ if (mpq_cmp (num2, arr2[rowmap[i]]) < 0)
+ {
+ rval = 0;
+ if(!msg_lvl)
+ {
+ MESSAGE(0, "constraint %s artificial (%lg) bellow lower"
+ " bound (%lg), actual LHS (%lg), actual RHS (%lg)",
+ qslp->rownames[i], mpq_get_d (num2),
+ mpq_get_d (arr2[rowmap[i]]), mpq_get_d (rhs_copy[i]),
+ mpq_get_d (arr1[i]));
+ }
+ goto CLEANUP;
+ }
+ else if (mpq_cmp (num2, arr4[rowmap[i]]) > 0)
+ {
+ rval = 0;
+ if(!msg_lvl)
+ {
+ MESSAGE(0, "constraint %s artificial (%lg) bellow lower bound"
+ " (%lg)", qslp->rownames[i], mpq_get_d (num2),
+ mpq_get_d (arr4[rowmap[i]]));
+ }
+ goto CLEANUP;
+ }
+ }
+
+ /* compute the upper and lower bound dual variables, note that dl is the dual
+ * of the lower bounds, and du the dual of the upper bound, dl >= 0 and du <=
+ * 0 and A^t y + Idl + Idu = c, and the dual objective value is
+ * max y*b + l*dl + u*du, we colapse both vector dl and du into dz, note that
+ * if we are maximizing, then dl <= 0 and du >=0 */
+ dz = mpq_EGlpNumAllocArray (qslp->ncols);
+ arr2 = qslp->obj;
+ arr3 = qslp->lower;
+ arr4 = qslp->upper;
+ for (i = qslp->nstruct; i--;)
+ {
+ col = structmap[i];
+ mpq_mul (num1, arr2[col], p_sol[i]);
+ mpq_add (p_obj, p_obj, num1);
+ arr1 = qslp->A.matval + qslp->A.matbeg[col];
+ iarr1 = qslp->A.matind + qslp->A.matbeg[col];
+ mpq_set (num1, arr2[col]);
+ for (j = qslp->A.matcnt[col]; j--;)
+ {
+ mpq_mul (num2, arr1[j], d_sol[iarr1[j]]);
+ mpq_sub (num1, num1, num2);
+ }
+ mpq_set (dz[col], num1);
+ /* objective update */
+ if (objsense * mpq_cmp_ui (dz[col], 0UL, 1UL) > 0)
+ {
+ mpq_mul (num3, dz[col], arr3[col]);
+ mpq_add (d_obj, d_obj, num3);
+ }
+ else
+ {
+ mpq_mul (num3, dz[col], arr4[col]);
+ mpq_add (d_obj, d_obj, num3);
+ }
+ /* now we check that only when the logical is tight then the dual
+ * variable may be non-zero, also check for primal feasibility with respect
+ * to lower/upper bounds. */
+ mpq_set_ui (num2, 0UL, 1UL);
+ if (objsense * mpq_cmp_ui (dz[col], 0UL, 1UL) > 0)
+ {
+ mpq_sub (num1, p_sol[i], arr3[col]);
+ mpq_mul (num2, num1, dz[col]);
+ }
+ if (mpq_cmp_ui (num2, 0UL, 1UL) != 0)
+ {
+ rval = 0;
+ if(!msg_lvl)
+ {
+ MESSAGE(0, "lower bound (%s,%d) slack (%lg) and dual variable (%lg)"
+ " don't satisfy complementary slacknes %s",
+ qslp->colnames[i], i, mpq_get_d(num1), mpq_get_d(dz[col]),
+ "(real)");
+ }
+ goto CLEANUP;
+ }
+ mpq_set_ui (num2, 0UL, 1UL);
+ if (objsense * mpq_cmp_ui (dz[col], 0UL, 1UL) < 0)
+ {
+ mpq_sub (num1, p_sol[i], arr4[col]);
+ mpq_mul (num2, num1, dz[col]);
+ }
+ if (mpq_cmp_ui (num2, 0UL, 1UL) != 0)
+ {
+ rval = 0;
+ if(!msg_lvl)
+ {
+ MESSAGE(0, "upper bound (%lg) variable (%lg) and dual variable"
+ " (%lg) don't satisfy complementary slacknes for variable"
+ " (%s,%d) %s", mpq_get_d(arr4[col]), mpq_get_d(p_sol[i]),
+ mpq_get_d(dz[col]), qslp->colnames[i], i, "(real)");
+ }
+ goto CLEANUP;
+ }
+ }
+ /* complenetary slackness checked, now update the same for the logical
+ * variables */
+ for (i = qslp->nrows; i--;)
+ {
+ col = rowmap[i];
+ mpq_mul (num1, arr2[col], p_sol[i + qslp->nstruct]);
+ WARNING (mpq_cmp (arr2[col], mpq_zeroLpNum), "logical variable %s with "
+ "non-zero objective function %lf", qslp->rownames[i],
+ mpq_get_d (arr2[col]));
+ mpq_add (p_obj, p_obj, num1);
+ arr1 = qslp->A.matval + qslp->A.matbeg[col];
+ iarr1 = qslp->A.matind + qslp->A.matbeg[col];
+ mpq_set (num1, arr2[col]);
+ for (j = qslp->A.matcnt[col]; j--;)
+ {
+ mpq_mul (num2, arr1[j], d_sol[iarr1[j]]);
+ mpq_sub (num1, num1, num2);
+ }
+ mpq_set (dz[col], num1);
+ /* objective update */
+ if (objsense * mpq_cmp_ui (dz[col], 0UL, 1UL) > 0)
+ {
+ mpq_mul (num3, dz[col], arr3[col]);
+ mpq_add (d_obj, d_obj, num3);
+ }
+ else
+ {
+ mpq_mul (num3, dz[col], arr4[col]);
+ mpq_add (d_obj, d_obj, num3);
+ }
+ /* now we check that only when the primal variable is tight then the dual
+ * variable may be non-zero, also check for primal feasibility with respect
+ * to lower/upper bounds. */
+ mpq_set_ui (num2, 0UL, 1UL);
+ if (objsense * mpq_cmp_ui (dz[col], 0UL, 1UL) > 0)
+ {
+ mpq_sub (num1, p_sol[i + qslp->nstruct], arr3[col]);
+ mpq_mul (num2, num1, dz[col]);
+ }
+ if (mpq_cmp_ui (num2, 0UL, 1UL) != 0)
+ {
+ rval = 0;
+ if(!msg_lvl)
+ {
+ MESSAGE(0, "lower bound (%s,%d) slack (%lg) and dual variable (%lg)"
+ " don't satisfy complementary slacknes %s",
+ qslp->colnames[col], i, mpq_get_d(num1), mpq_get_d(dz[col]),
+ "(real)");
+ }
+ goto CLEANUP;
+ }
+ mpq_set_ui (num2, 0UL, 1UL);
+ if (objsense * mpq_cmp_ui (dz[col], 0UL, 1UL) < 0)
+ {
+ mpq_sub (num1, p_sol[i + qslp->nstruct], arr4[col]);
+ mpq_mul (num2, num1, dz[col]);
+ }
+ if (mpq_cmp_ui (num2, 0UL, 1UL) != 0)
+ {
+ rval = 0;
+ if(!msg_lvl)
+ {
+ MESSAGE(0, "upper bound (%lg) variable (%lg) and dual variable"
+ " (%lg) don't satisfy complementary slacknes for variable "
+ "(%s,%d) %s", mpq_get_d(arr4[col]),
+ mpq_get_d(p_sol[i+qslp->nstruct]), mpq_get_d(dz[col]), qslp->colnames[col], i,
+ "(real)");
+ }
+ goto CLEANUP;
+ }
+ }
+
+ /* now check the objective values */
+ if (mpq_cmp (p_obj, d_obj) != 0)
+ {
+ rval = 0;
+ if(!msg_lvl)
+ {
+ MESSAGE(0, "primal and dual objective value differ %lg %lg",
+ mpq_get_d(p_obj), mpq_get_d(d_obj));
+ }
+ goto CLEANUP;
+ }
+ /* now we report optimality */
+ if(!msg_lvl)
+ {
+ MESSAGE(0, "Problem solved to optimality, LP value %lg", mpq_get_d(p_obj));
+ }
+ /* now we load into cache the solution */
+ if (!p->cache)
+ {
+ p->cache = EGsMalloc (mpq_ILLlp_cache, 1);
+ mpq_EGlpNumInitVar (p->cache->val);
+ mpq_ILLlp_cache_init (p->cache);
+ }
+ if (qslp->nrows != p->cache->nrows || qslp->nstruct != p->cache->nstruct)
+ {
+ mpq_ILLlp_cache_free (p->cache);
+ EGcallD(mpq_ILLlp_cache_alloc (p->cache, qslp->nstruct, qslp->nrows));
+ }
+ p->cache->status = QS_LP_OPTIMAL;
+ p->qstatus = QS_LP_OPTIMAL;
+ p->lp->basisstat.optimal = 1;
+ mpq_set (p->cache->val, p_obj);
+ for (i = qslp->nstruct; i--;)
+ {
+ mpq_set (p->cache->x[i], p_sol[i]);
+ mpq_set (p->cache->rc[i], dz[structmap[i]]);
+ }
+ for (i = qslp->nrows; i--;)
+ {
+ mpq_set (p->cache->slack[i], p_sol[i + qslp->nstruct]);
+ mpq_set (p->cache->pi[i], d_sol[i]);
+ }
+
+ /* save the problem and solution if enablred */
+#if QSEXACT_SAVE_OPTIMAL
+ {
+ char stmp[1024];
+ EGioFile_t *out_f = 0;
+ snprintf (stmp, 1023, "%s-opt%03d.lp", p->name ? p->name : "UNNAMED",
+ QSEXACT_SAVE_OPTIMAL_IND);
+ if (mpq_QSwrite_prob (p, stmp, "LP"))
+ {
+ rval = 0;
+ MESSAGE (0, "Couldn't write output problem %s", stmp);
+ goto CLEANUP;
+ }
+ snprintf (stmp, 1023, "%s-opt%03d.sol.gz", p->name ? p->name : "UNNAMED",
+ QSEXACT_SAVE_OPTIMAL_IND);
+ if (!(out_f = EGioOpen (stmp, "w+")))
+ {
+ rval = 0;
+ MESSAGE (0, "Couldn't open solution file %s", stmp);
+ goto CLEANUP;
+ }
+ if (QSexact_print_sol (p, out_f))
+ {
+ rval = 0;
+ MESSAGE (0, "Couldn't write output solution %s", stmp);
+ goto CLEANUP;
+ }
+ EGioClose (out_f);
+ QSEXACT_SAVE_OPTIMAL_IND++;
+ }
+#endif
+ rval = 1;
+
+ /* ending */
+CLEANUP:
+ mpq_EGlpNumFreeArray (dz);
+ mpq_EGlpNumFreeArray (rhs_copy);
+ mpq_clear (num1);
+ mpq_clear (num2);
+ mpq_clear (num3);
+ mpq_clear (p_obj);
+ mpq_clear (d_obj);
+ return rval;
+}
+
+/* ========================================================================= */
+int QSexact_infeasible_test (mpq_QSdata * p,
+ mpq_t * d_sol)
+{
+ /* local variables */
+ register int i,
+ j;
+ int *iarr1;
+ mpq_ILLlpdata *qslp = p->lp->O;
+ mpq_t *arr1,
+ *arr2,
+ *arr3,
+ *arr4;
+ mpq_t *dl = 0,
+ *du = 0;
+ int const msg_lvl = __QS_SB_VERB <= DEBUG ? 0 : 100000 * (1 - p->simplex_display);
+ int rval = 1; /* store whether or not the solution is optimal, we start
+ * assuming it is. */
+ mpq_t num1,
+ num2,
+ num3,
+ d_obj;
+ mpq_init (num1);
+ mpq_init (num2);
+ mpq_init (num3);
+ mpq_init (d_obj);
+ mpq_set_ui (d_obj, 0UL, 1UL);
+
+ /* compute the dual objective value */
+ arr2 = qslp->rhs;
+ for (i = qslp->nrows; i--;)
+ {
+ mpq_mul (num1, arr2[i], d_sol[i]);
+ mpq_add (d_obj, d_obj, num1);
+ }
+
+ /* compute the upper and lower bound dual variables, note that dl is the dual
+ * of the lower bounds, and du the dual of the upper bound, dl <= 0 and du >=
+ * 0 and A^t y + Idl + Idu = c, and the dual objective value is
+ * max y*b + l*dl + u*du */
+ du = mpq_EGlpNumAllocArray (qslp->ncols);
+ dl = mpq_EGlpNumAllocArray (qslp->ncols);
+ arr3 = qslp->lower;
+ arr4 = qslp->upper;
+ for (i = qslp->ncols; i--;)
+ {
+ arr1 = qslp->A.matval + qslp->A.matbeg[i];
+ iarr1 = qslp->A.matind + qslp->A.matbeg[i];
+ mpq_set_ui (num1, 0UL, 1UL);
+ mpq_set_ui (du[i], 0UL, 1UL);
+ mpq_set_ui (dl[i], 0UL, 1UL);
+ for (j = qslp->A.matcnt[i]; j--;)
+ {
+ mpq_mul (num2, arr1[j], d_sol[iarr1[j]]);
+ mpq_sub (num1, num1, num2);
+ }
+ if (mpq_cmp_ui (num1, 0UL, 1UL) < 0)
+ mpq_set (du[i], num1);
+ else
+ mpq_set (dl[i], num1);
+ if (mpq_equal (arr4[i], mpq_ILL_MAXDOUBLE) &&
+ mpq_cmp_ui (du[i], 0UL, 1UL) != 0)
+ {
+ rval = 0;
+ if(!msg_lvl)
+ {
+ MESSAGE(0, "upper bound of variable is INFTY, and it's dual is "
+ "non-zero %lg", mpq_get_d(du[i]));
+ }
+ goto CLEANUP;
+ }
+ if (mpq_equal (arr3[i], mpq_ILL_MINDOUBLE) &&
+ mpq_cmp_ui (dl[i], 0UL, 1UL) != 0)
+ {
+ rval = 0;
+ if(!msg_lvl)
+ {
+ MESSAGE(0, "lower bound of variable is -INFTY, and it's dual is "
+ "non-zero %lg", mpq_get_d(dl[i]));
+ }
+ goto CLEANUP;
+ }
+ mpq_mul (num3, dl[i], arr3[i]);
+ mpq_add (d_obj, d_obj, num3);
+ mpq_mul (num3, du[i], arr4[i]);
+ mpq_add (d_obj, d_obj, num3);
+ }
+ /* now check the objective values */
+ if (mpq_cmp_ui (d_obj, 0UL, 1UL) <= 0)
+ {
+ rval = 0;
+ if(!msg_lvl)
+ {
+ MESSAGE(0, "dual ray is feasible, but objective is non "
+ "positive %lg", mpq_get_d(d_obj));
+ }
+ goto CLEANUP;
+ }
+ p->qstatus = QS_LP_INFEASIBLE;
+
+ /* ending */
+CLEANUP:
+ mpq_EGlpNumFreeArray (dl);
+ mpq_EGlpNumFreeArray (du);
+ mpq_clear (num1);
+ mpq_clear (num2);
+ mpq_clear (num3);
+ mpq_clear (d_obj);
+ return rval;
+}
+
+/* ========================================================================= */
+/** @brief Used as separator while printing output to the screen (controled by
+ * enabling simplex_display in the mpq_QSdata */
+/* ========================================================================= */
+static const char __sp[81] =
+ "================================================================================";
+
+/* ========================================================================= */
+/** @brief print into screen (if enable) a message indicating that we have
+ * successfully prove infeasibility, and save (if y is non
+ * NULL ) the dual ray solution provided in y_mpq.
+ * @param p_mpq the problem data.
+ * @param y where to store the optimal dual solution (if not null).
+ * @param y_mpq the optimal dual solution.
+ * */
+/* ========================================================================= */
+static void infeasible_output (mpq_QSdata * p_mpq,
+ mpq_t * const y,
+ mpq_t * y_mpq)
+{
+ if (p_mpq->simplex_display)
+ {
+ QSlog("Problem Is Infeasible");
+ }
+ if (y)
+ {
+ unsigned sz = __EGlpNumArraySize (y_mpq);
+ while (sz--)
+ mpq_set (y[sz], y_mpq[sz]);
+ }
+}
+
+/* ========================================================================= */
+/** @brief print into screen (if enable) a message indicating that we have
+ * successfully solved the problem at optimality, and save (if x and y are non
+ * NULL respectivelly) the optimal primal/dual solution provided in x_mpq and
+ * y_mpq.
+ * @param p_mpq the problem data.
+ * @param x where to store the optimal primal solution (if not null).
+ * @param y where to store the optimal dual solution (if not null).
+ * @param x_mpq the optimal primal solution.
+ * @param y_mpq the optimal dual solution.
+ * */
+/* ========================================================================= */
+static void optimal_output (mpq_QSdata * p_mpq,
+ mpq_t * const x,
+ mpq_t * const y,
+ mpq_t * x_mpq,
+ mpq_t * y_mpq)
+{
+ if (p_mpq->simplex_display)
+ {
+ QSlog("Problem Solved Exactly");
+ }
+ if (y)
+ {
+ unsigned sz = __EGlpNumArraySize (y_mpq);
+ while (sz--)
+ mpq_set (y[sz], y_mpq[sz]);
+ }
+ if (x)
+ {
+ unsigned sz = __EGlpNumArraySize (x_mpq);
+ while (sz--)
+ mpq_set (x[sz], x_mpq[sz]);
+ }
+}
+
+/* ========================================================================= */
+/** @brief get the status for a given basis in rational arithmetic, it should
+ * also leave everything set to get primal/dual solutions when needed.
+ * */
+static int QSexact_basis_status (mpq_QSdata * p_mpq,
+ int *status,
+ QSbasis * const basis,
+ const int msg_lvl,
+ int *const simplexalgo)
+{
+ int rval = 0,
+ singular;
+ mpq_feas_info fi;
+ EGtimer_t local_timer;
+ mpq_EGlpNumInitVar (fi.totinfeas);
+ EGtimerReset (&local_timer);
+ EGtimerStart (&local_timer);
+ EGcallD(mpq_QSload_basis (p_mpq, basis));
+ if (p_mpq->cache)
+ {
+ mpq_ILLlp_cache_free (p_mpq->cache);
+ mpq_clear (p_mpq->cache->val);
+ ILL_IFFREE (p_mpq->cache, mpq_ILLlp_cache);
+ }
+ p_mpq->qstatus = QS_LP_MODIFIED;
+ if(p_mpq->qslp->sinfo)
+ {
+ mpq_ILLlp_sinfo_free(p_mpq->qslp->sinfo);
+ ILL_IFFREE(p_mpq->qslp->sinfo, mpq_ILLlp_sinfo);
+ }
+ if(p_mpq->qslp->rA)
+ {
+ mpq_ILLlp_rows_clear (p_mpq->qslp->rA);
+ ILL_IFFREE (p_mpq->qslp->rA, mpq_ILLlp_rows);
+ }
+ mpq_free_internal_lpinfo (p_mpq->lp);
+ mpq_init_internal_lpinfo (p_mpq->lp);
+ EGcallD(mpq_build_internal_lpinfo (p_mpq->lp));
+ mpq_ILLfct_set_variable_type (p_mpq->lp);
+ EGcallD(mpq_ILLbasis_load (p_mpq->lp, p_mpq->basis));
+ EGcallD(mpq_ILLbasis_factor (p_mpq->lp, &singular));
+ memset (&(p_mpq->lp->basisstat), 0, sizeof (mpq_lp_status_info));
+ mpq_ILLfct_compute_piz (p_mpq->lp);
+ mpq_ILLfct_compute_dz (p_mpq->lp);
+ mpq_ILLfct_compute_xbz (p_mpq->lp);
+ mpq_ILLfct_check_pfeasible (p_mpq->lp, &fi, mpq_zeroLpNum);
+ mpq_ILLfct_check_dfeasible (p_mpq->lp, &fi, mpq_zeroLpNum);
+ mpq_ILLfct_set_status_values (p_mpq->lp, fi.pstatus, fi.dstatus, PHASEII,
+ PHASEII);
+ if (p_mpq->lp->basisstat.optimal)
+ {
+ *status = QS_LP_OPTIMAL;
+ EGcallD(mpq_QSgrab_cache (p_mpq, QS_LP_OPTIMAL));
+ }
+ else if (p_mpq->lp->basisstat.primal_infeasible
+ || p_mpq->lp->basisstat.dual_unbounded)
+ {
+ if (*status == QS_LP_INFEASIBLE)
+ *simplexalgo = PRIMAL_SIMPLEX;
+ *status = QS_LP_INFEASIBLE;
+ p_mpq->lp->final_phase = PRIMAL_PHASEI;
+ p_mpq->lp->pIpiz = mpq_EGlpNumAllocArray (p_mpq->lp->nrows);
+ mpq_ILLfct_compute_phaseI_piz (p_mpq->lp);
+ }
+ else if (p_mpq->lp->basisstat.primal_unbounded)
+ *status = QS_LP_UNBOUNDED;
+ else
+ *status = QS_LP_UNSOLVED;
+ EGtimerStop (&local_timer);
+ if(!msg_lvl)
+ {
+ MESSAGE(0, "Performing Rational Basic Solve on %s, %s, check"
+ " done in %lg seconds, PS %s %lg, DS %s %lg", p_mpq->name,
+ (*status == QS_LP_OPTIMAL) ? "RAT_optimal" :
+ ((*status == QS_LP_INFEASIBLE) ? "RAT_infeasible" :
+ ((*status == QS_LP_UNBOUNDED) ? "RAT_unbounded" : "RAT_unsolved")),
+ local_timer.time, p_mpq->lp->basisstat.primal_feasible ?
+ "F":(p_mpq->lp->basisstat.primal_infeasible ? "I" : "U"),
+ p_mpq->lp->basisstat.primal_feasible ?
+ mpq_get_d(p_mpq->lp->objval) :
+ (p_mpq->lp->basisstat.primal_infeasible ?
+ mpq_get_d(p_mpq->lp->pinfeas) : mpq_get_d(p_mpq->lp->objbound)),
+ p_mpq->lp->basisstat.dual_feasible ?
+ "F":(p_mpq->lp->basisstat.dual_infeasible ? "I" : "U"),
+ p_mpq->lp->basisstat.dual_feasible ? mpq_get_d(p_mpq->lp->dobjval)
+ :(p_mpq->lp->basisstat.dual_infeasible ?
+ mpq_get_d(p_mpq->lp->dinfeas) : mpq_get_d(p_mpq->lp->objbound)) );
+ }
+CLEANUP:
+ mpq_EGlpNumClearVar (fi.totinfeas);
+ return rval;
+}
+
+/* ========================================================================= */
+/** @brief test whether given basis is primal and dual feasible in rational arithmetic.
+ * @param p_mpq the problem data.
+ * @param basis basis to be tested.
+ * @param result where to store whether given basis is primal and dual feasible.
+ * @param msg_lvl message level.
+ */
+int QSexact_basis_optimalstatus(
+ mpq_QSdata * p_mpq,
+ QSbasis* basis,
+ char* result,
+ const int msg_lvl
+ )
+{
+ int rval = 0,
+ singular;
+ mpq_feas_info fi;
+ EGtimer_t local_timer;
+
+ /* test primal and dual feasibility of basic solution */
+ mpq_EGlpNumInitVar (fi.totinfeas);
+
+ EGtimerReset (&local_timer);
+ EGtimerStart (&local_timer);
+
+ EGcallD(mpq_QSload_basis (p_mpq, basis));
+
+ if (p_mpq->cache)
+ {
+ mpq_ILLlp_cache_free (p_mpq->cache);
+ mpq_clear (p_mpq->cache->val);
+ ILL_IFFREE (p_mpq->cache, mpq_ILLlp_cache);
+ }
+ p_mpq->qstatus = QS_LP_MODIFIED;
+
+ if(p_mpq->qslp->sinfo)
+ {
+ mpq_ILLlp_sinfo_free(p_mpq->qslp->sinfo);
+ ILL_IFFREE(p_mpq->qslp->sinfo, mpq_ILLlp_sinfo);
+ }
+ if(p_mpq->qslp->rA)
+ {
+ mpq_ILLlp_rows_clear (p_mpq->qslp->rA);
+ ILL_IFFREE (p_mpq->qslp->rA, mpq_ILLlp_rows);
+ }
+
+ mpq_free_internal_lpinfo (p_mpq->lp);
+ mpq_init_internal_lpinfo (p_mpq->lp);
+ EGcallD(mpq_build_internal_lpinfo (p_mpq->lp));
+
+ mpq_ILLfct_set_variable_type (p_mpq->lp);
+
+ EGcallD(mpq_ILLbasis_load (p_mpq->lp, p_mpq->basis));
+ EGcallD(mpq_ILLbasis_factor (p_mpq->lp, &singular));
+
+ memset (&(p_mpq->lp->basisstat), 0, sizeof (mpq_lp_status_info));
+ mpq_ILLfct_compute_piz (p_mpq->lp);
+ mpq_ILLfct_compute_dz (p_mpq->lp);
+ mpq_ILLfct_compute_xbz (p_mpq->lp);
+ mpq_ILLfct_check_pfeasible (p_mpq->lp, &fi, mpq_zeroLpNum);
+ mpq_ILLfct_check_dfeasible (p_mpq->lp, &fi, mpq_zeroLpNum);
+ mpq_ILLfct_set_status_values (p_mpq->lp, fi.pstatus, fi.dstatus, PHASEII, PHASEII);
+
+ if( p_mpq->lp->basisstat.optimal )
+ {
+ *result = 1;
+ }
+ else
+ {
+ *result = 0;
+ }
+
+ EGtimerStop (&local_timer);
+
+ if( !msg_lvl )
+ {
+ MESSAGE(0, "Performing rational solution check for accuratelp on %s, sucess=%s",
+ p_mpq->name,
+ *result ? "YES" : "NO");
+ }
+
+ CLEANUP:
+ mpq_EGlpNumClearVar (fi.totinfeas);
+ return rval;
+}
+
+/* ========================================================================= */
+/** @brief test whether given basis is dual feasible in rational arithmetic.
+ * @param p_mpq the problem data.
+ * @param basis basis to be tested.
+ * @param result where to store whether given basis is dual feasible.
+ * @param dobjval where to store dual solution value in case of dual feasibility (if not NULL).
+ * @param msg_lvl message level.
+ */
+int QSexact_basis_dualstatus(
+ mpq_QSdata * p_mpq,
+ QSbasis* basis,
+ char* result,
+ mpq_t* dobjval,
+ const int msg_lvl
+ )
+{
+ int rval = 0,
+ singular;
+ mpq_feas_info fi;
+ EGtimer_t local_timer;
+
+ mpq_EGlpNumInitVar (fi.totinfeas);
+ EGtimerReset (&local_timer);
+ EGtimerStart (&local_timer);
+ EGcallD(mpq_QSload_basis (p_mpq, basis));
+ if (p_mpq->cache)
+ {
+ mpq_ILLlp_cache_free (p_mpq->cache);
+ mpq_clear (p_mpq->cache->val);
+ ILL_IFFREE (p_mpq->cache, mpq_ILLlp_cache);
+ }
+ p_mpq->qstatus = QS_LP_MODIFIED;
+
+ if(p_mpq->qslp->sinfo)
+ {
+ mpq_ILLlp_sinfo_free(p_mpq->qslp->sinfo);
+ ILL_IFFREE(p_mpq->qslp->sinfo, mpq_ILLlp_sinfo);
+ }
+
+ if(p_mpq->qslp->rA)
+ {
+ mpq_ILLlp_rows_clear (p_mpq->qslp->rA);
+ ILL_IFFREE (p_mpq->qslp->rA, mpq_ILLlp_rows);
+ }
+
+ mpq_free_internal_lpinfo (p_mpq->lp);
+ mpq_init_internal_lpinfo (p_mpq->lp);
+ EGcallD(mpq_build_internal_lpinfo (p_mpq->lp));
+ mpq_ILLfct_set_variable_type (p_mpq->lp);
+ EGcallD(mpq_ILLbasis_load (p_mpq->lp, p_mpq->basis));
+ EGcallD(mpq_ILLbasis_factor (p_mpq->lp, &singular));
+
+ memset (&(p_mpq->lp->basisstat), 0, sizeof (mpq_lp_status_info));
+ mpq_ILLfct_compute_piz (p_mpq->lp);
+ mpq_ILLfct_compute_dz (p_mpq->lp);
+ mpq_ILLfct_compute_dobj(p_mpq->lp);
+ mpq_ILLfct_check_dfeasible (p_mpq->lp, &fi, mpq_zeroLpNum);
+ mpq_ILLfct_set_status_values (p_mpq->lp, fi.pstatus, fi.dstatus, PHASEII, PHASEII);
+
+ if( p_mpq->lp->basisstat.dual_feasible )
+ {
+ *result = 1;
+ if( dobjval )
+ {
+ mpq_EGlpNumCopy(*dobjval, p_mpq->lp->dobjval);
+ }
+ }
+ else if( p_mpq->lp->basisstat.dual_infeasible )
+ {
+ *result = 0;
+ }
+ else
+ {
+ TESTG((rval=!(p_mpq->lp->basisstat.dual_unbounded)), CLEANUP, "Internal BUG, problem should be dual unbounded but is not");
+ *result = 1;
+ if( dobjval )
+ {
+ mpq_EGlpNumCopy(*dobjval, p_mpq->lp->objbound);
+ }
+ }
+
+ EGtimerStop (&local_timer);
+
+ if(!msg_lvl)
+ {
+ MESSAGE(0, "Performing Rational Basic Test on %s, check done in %lg seconds, DS %s %lg",
+ p_mpq->name, local_timer.time,
+ p_mpq->lp->basisstat.dual_feasible ? "F": (p_mpq->lp->basisstat.dual_infeasible ? "I" : "U"),
+ p_mpq->lp->basisstat.dual_feasible ? mpq_get_d(p_mpq->lp->dobjval) : (p_mpq->lp->basisstat.dual_infeasible ? mpq_get_d(p_mpq->lp->dinfeas) : mpq_get_d(p_mpq->lp->objbound)) );
+ }
+
+CLEANUP:
+ mpq_EGlpNumClearVar (fi.totinfeas);
+ return rval;
+}
+
+/* ========================================================================= */
+/** @brief test whether given basis is dual feasible in rational arithmetic.
+ * if wanted it will first directly test the corresponding approximate dual and primal solution
+ * (corrected via dual variables for bounds and primal variables for slacks if possible) for optimality
+ * before performing the dual feasibility test on the more expensive exact basic solution.
+ * @param p_mpq the problem data.
+ * @param basis basis to be tested.
+ * @param useprestep whether to directly test approximate primal and dual solution first.
+ * @param dbl_p_sol approximate primal solution to use in prestep
+ * (NULL in order to compute it by dual simplex in double precision with given starting basis).
+ * @param dbl_d_sol approximate dual solution to use in prestep
+ * (NULL in order to compute it by dual simplex in double precision with given starting basis).
+ * @param result where to store whether given basis is dual feasible.
+ * @param dobjval where to store dual solution value in case of dual feasibility (if not NULL).
+ * @param msg_lvl message level.
+ */
+int QSexact_verify (
+ mpq_QSdata * p_mpq,
+ QSbasis* basis,
+ int useprestep,
+ double* dbl_p_sol,
+ double* dbl_d_sol,
+ char* result,
+ mpq_t* dobjval,
+ const int msg_lvl
+)
+{
+ int rval = 0;
+
+ //assert(basis);
+ //assert(basis->nstruct);
+
+ *result = 0;
+
+ if( useprestep )
+ {
+ mpq_t *x_mpq = 0;
+ mpq_t *y_mpq = 0;
+ int status = 0;
+
+ if( dbl_p_sol == NULL || dbl_d_sol == NULL )
+ {
+ dbl_QSdata *p_dbl = 0;
+ double *x_dbl = 0;
+ double *y_dbl = 0;
+
+ /* create double problem, warmstart with given basis and solve it using double precision
+ * this is only done to get approximate primal and dual solution corresponding to the given basis
+ */
+ p_dbl = QScopy_prob_mpq_dbl(p_mpq, "dbl_problem");
+
+ dbl_QSload_basis(p_dbl, basis);
+ rval = dbl_ILLeditor_solve(p_dbl, DUAL_SIMPLEX);
+ CHECKRVALG(rval, CLEANUP);
+
+ rval = dbl_QSget_status(p_dbl, &status);
+ CHECKRVALG(rval, CLEANUP);
+
+ if( status == QS_LP_OPTIMAL )
+ {
+ /* get continued fraction approximation of approximate solution */
+ x_dbl = dbl_EGlpNumAllocArray(p_dbl->qslp->ncols);
+ y_dbl = dbl_EGlpNumAllocArray(p_dbl->qslp->nrows);
+
+ rval = dbl_QSget_x_array(p_dbl, x_dbl);
+ CHECKRVALG(rval, CLEANUP);
+ rval = dbl_QSget_pi_array(p_dbl, y_dbl);
+ CHECKRVALG(rval, CLEANUP);
+ x_mpq = QScopy_array_dbl_mpq(x_dbl);
+ y_mpq = QScopy_array_dbl_mpq(y_dbl);
+
+ /* test optimality of constructed solution */
+ basis = dbl_QSget_basis(p_dbl);
+ rval = QSexact_optimal_test(p_mpq, x_mpq, y_mpq, basis);
+ if( rval )
+ {
+ *result = 1;
+ if( dobjval )
+ {
+ rval = mpq_QSget_objval(p_mpq, dobjval);
+ if( rval )
+ *result = 0;
+ }
+ }
+ if( !msg_lvl )
+ {
+ MESSAGE(0, "Performing approximated solution check on %s, sucess=%s dobjval=%lg",
+ p_mpq->name,
+ *result ? "YES" : "NO",
+ *result ? mpq_get_d(*dobjval) : mpq_get_d(*dobjval));
+ }
+ }
+ CLEANUP:
+ dbl_EGlpNumFreeArray(x_dbl);
+ dbl_EGlpNumFreeArray(y_dbl);
+ mpq_EGlpNumFreeArray(x_mpq);
+ mpq_EGlpNumFreeArray(y_mpq);
+ dbl_QSfree_prob(p_dbl);
+ rval = 0;
+ }
+ else
+ {
+ dbl_QSdata *p_dbl = 0;
+ int i;
+
+ /* for some reason, this help to avoid fails in QSexact_basis_dualstatus() after
+ * the test here fails, i.e., if we would not perform the test here, than QSexact_basis_dualstatus() would normally not fail
+ * something happens with the basis... if we do not set up the dbl-prob (?) ????????????????????????
+ */
+ p_dbl = QScopy_prob_mpq_dbl(p_mpq, "dbl_problem");
+ dbl_QSload_basis(p_dbl, basis);
+
+ x_mpq = mpq_EGlpNumAllocArray(p_mpq->qslp->ncols);
+ y_mpq = mpq_EGlpNumAllocArray(p_mpq->qslp->nrows);
+
+ /* get continued fraction approximation of approximate solution */
+ for( i = 0; i < p_mpq->qslp->ncols; ++i )
+ mpq_EGlpNumSet(x_mpq[i], dbl_p_sol[i]);
+
+ for( i = 0; i < p_mpq->qslp->nrows; ++i )
+ mpq_EGlpNumSet(y_mpq[i], dbl_d_sol[i]);
+
+ /* test optimality of constructed solution */
+ basis = dbl_QSget_basis(p_dbl);
+ rval = QSexact_optimal_test(p_mpq, x_mpq, y_mpq, basis);
+ if( rval )
+ {
+ *result = 1;
+ if( dobjval )
+ {
+ rval = mpq_QSget_objval(p_mpq, dobjval);
+ if( rval )
+ *result = 0;
+ }
+ }
+ if( !msg_lvl )
+ {
+ MESSAGE(0, "Performing approximated solution check on %s, sucess=%s dobjval=%lg",
+ p_mpq->name,
+ *result ? "YES" : "NO",
+ *result ? mpq_get_d(*dobjval) : mpq_get_d(*dobjval));
+ }
+ mpq_EGlpNumFreeArray(x_mpq);
+ mpq_EGlpNumFreeArray(y_mpq);
+ dbl_QSfree_prob(p_dbl);
+ rval = 0;
+ }
+ }
+
+ if( !(*result) )
+ {
+ rval = QSexact_basis_dualstatus(p_mpq, basis, result, dobjval, msg_lvl);
+ if( !msg_lvl )
+ {
+ MESSAGE(0, "Performing rational solution check on %s, sucess=%s dobjval=%lg",
+ p_mpq->name,
+ *result ? "YES" : "NO",
+ *result ? mpq_get_d(*dobjval) : mpq_get_d(*dobjval));
+ }
+ }
+
+ return rval;
+}
+
+/* ========================================================================= */
+int QSexact_solver (mpq_QSdata * p_mpq,
+ mpq_t * const x,
+ mpq_t * const y,
+ QSbasis * const ebasis,
+ int simplexalgo,
+ int *status)
+{
+ /* local variables */
+ int last_status = 0, last_iter = 0;
+ QSbasis *basis = 0;
+ unsigned precision = EGLPNUM_PRECISION;
+ int rval = 0,
+ it = QS_EXACT_MAX_ITER;
+ dbl_QSdata *p_dbl = 0;
+ mpf_QSdata *p_mpf = 0;
+ double *x_dbl = 0,
+ *y_dbl = 0;
+ mpq_t *x_mpq = 0,
+ *y_mpq = 0;
+ mpf_t *x_mpf = 0,
+ *y_mpf = 0;
+ int const msg_lvl = __QS_SB_VERB <= DEBUG ? 0: (1 - p_mpq->simplex_display) * 10000;
+ *status = 0;
+ /* save the problem if we are really debugging */
+ if(DEBUG >= __QS_SB_VERB)
+ {
+ EGcallD(mpq_QSwrite_prob(p_mpq, "qsxprob.lp","LP"));
+ }
+ /* try first with doubles */
+ if (p_mpq->simplex_display || DEBUG >= __QS_SB_VERB)
+ {
+ QSlog("Trying double precision");
+ }
+ p_dbl = QScopy_prob_mpq_dbl (p_mpq, "dbl_problem");
+ if(__QS_SB_VERB <= DEBUG) p_dbl->simplex_display = 1;
+ if (ebasis && ebasis->nstruct)
+ dbl_QSload_basis (p_dbl, ebasis);
+ if (dbl_ILLeditor_solve (p_dbl, simplexalgo))
+ {
+ MESSAGE(p_mpq->simplex_display ? 0: __QS_SB_VERB,
+ "double approximation failed, code %d, "
+ "continuing in extended precision", rval);
+ goto MPF_PRECISION;
+ }
+ EGcallD(dbl_QSget_status (p_dbl, status));
+ if ((*status == QS_LP_INFEASIBLE) &&
+ (p_dbl->lp->final_phase != PRIMAL_PHASEI) &&
+ (p_dbl->lp->final_phase != DUAL_PHASEII))
+ dbl_QSopt_primal (p_dbl, status);
+ EGcallD(dbl_QSget_status (p_dbl, status));
+ last_status = *status;
+ EGcallD(dbl_QSget_itcnt(p_dbl, 0, 0, 0, 0, &last_iter));
+ /* deal with the problem depending on what status we got from our optimizer */
+ switch (*status)
+ {
+ case QS_LP_OPTIMAL:
+ x_dbl = dbl_EGlpNumAllocArray (p_dbl->qslp->ncols);
+ y_dbl = dbl_EGlpNumAllocArray (p_dbl->qslp->nrows);
+ EGcallD(dbl_QSget_x_array (p_dbl, x_dbl));
+ EGcallD(dbl_QSget_pi_array (p_dbl, y_dbl));
+ x_mpq = QScopy_array_dbl_mpq (x_dbl);
+ y_mpq = QScopy_array_dbl_mpq (y_dbl);
+ dbl_EGlpNumFreeArray (x_dbl);
+ dbl_EGlpNumFreeArray (y_dbl);
+ basis = dbl_QSget_basis (p_dbl);
+ if (QSexact_optimal_test (p_mpq, x_mpq, y_mpq, basis))
+ {
+ optimal_output (p_mpq, x, y, x_mpq, y_mpq);
+ goto CLEANUP;
+ }
+ else
+ {
+ EGcallD(QSexact_basis_status (p_mpq, status, basis, msg_lvl, &simplexalgo));
+ if (*status == QS_LP_OPTIMAL)
+ {
+ if(!msg_lvl)
+ {
+ MESSAGE(0,"Retesting solution");
+ }
+ EGcallD(mpq_QSget_x_array (p_mpq, x_mpq));
+ EGcallD(mpq_QSget_pi_array (p_mpq, y_mpq));
+ if (QSexact_optimal_test (p_mpq, x_mpq, y_mpq, basis))
+ {
+ optimal_output (p_mpq, x, y, x_mpq, y_mpq);
+ goto CLEANUP;
+ }
+ else
+ {
+ last_status = *status = QS_LP_UNSOLVED;
+ }
+ }
+ else
+ {
+ if(!msg_lvl)
+ {
+ MESSAGE(0,"Status is not optimal, but %d", *status);
+ }
+ }
+ }
+ mpq_EGlpNumFreeArray (x_mpq);
+ mpq_EGlpNumFreeArray (y_mpq);
+ break;
+ case QS_LP_INFEASIBLE:
+ y_dbl = dbl_EGlpNumAllocArray (p_dbl->qslp->nrows);
+ if (dbl_QSget_infeas_array (p_dbl, y_dbl))
+ {
+ MESSAGE(p_mpq->simplex_display ? 0 : __QS_SB_VERB, "double approximation"
+ " failed, code %d, continuing in extended precision\n", rval);
+ goto MPF_PRECISION;
+ }
+ y_mpq = QScopy_array_dbl_mpq (y_dbl);
+ dbl_EGlpNumFreeArray (y_dbl);
+ if (QSexact_infeasible_test (p_mpq, y_mpq))
+ {
+ infeasible_output (p_mpq, y, y_mpq);
+ goto CLEANUP;
+ }
+ else
+ {
+ MESSAGE (msg_lvl, "Retesting solution in exact arithmetic");
+ basis = dbl_QSget_basis (p_dbl);
+ EGcallD(QSexact_basis_status (p_mpq, status, basis, msg_lvl, &simplexalgo));
+ #if 0
+ mpq_QSset_param (p_mpq, QS_PARAM_SIMPLEX_MAX_ITERATIONS, 1);
+ mpq_QSload_basis (p_mpq, basis);
+ mpq_QSfree_basis (basis);
+ EGcallD(mpq_ILLeditor_solve (p_mpq, simplexalgo));
+ EGcallD(mpq_QSget_status (p_mpq, status));
+ #endif
+ if (*status == QS_LP_INFEASIBLE)
+ {
+ mpq_EGlpNumFreeArray (y_mpq);
+ y_mpq = mpq_EGlpNumAllocArray (p_mpq->qslp->nrows);
+ EGcallD(mpq_QSget_infeas_array (p_mpq, y_mpq));
+ if (QSexact_infeasible_test (p_mpq, y_mpq))
+ {
+ infeasible_output (p_mpq, y, y_mpq);
+ goto CLEANUP;
+ }
+ else
+ {
+ last_status = *status = QS_LP_UNSOLVED;
+ }
+ }
+ }
+ mpq_EGlpNumFreeArray (y_mpq);
+ break;
+ case QS_LP_UNBOUNDED:
+ MESSAGE(p_mpq->simplex_display ? 0 : __QS_SB_VERB, "%s\n\tUnbounded "
+ "Problem found, not implemented to deal with this\n%s\n",__sp,__sp);
+ break;
+ case QS_LP_OBJ_LIMIT:
+ rval=1;
+ IFMESSAGE(p_mpq->simplex_display,"Objective limit reached (in floating point) ending now");
+ goto CLEANUP;
+ break;
+ default:
+ IFMESSAGE(p_mpq->simplex_display,"Re-trying inextended precision");
+ break;
+ }
+ /* if we reach this point, then we have to keep going, we use the previous
+ * basis ONLY if the previous precision think that it has the optimal
+ * solution, otherwise we start from scratch. */
+ precision = 128;
+ MPF_PRECISION:
+ dbl_QSfree_prob (p_dbl);
+ p_dbl = 0;
+ /* try with multiple precision floating points */
+ for (; it--; precision = (unsigned) (precision * 1.5))
+ {
+ QSexact_set_precision (precision);
+ if (p_mpq->simplex_display || DEBUG >= __QS_SB_VERB)
+ {
+ QSlog("Trying mpf with %u bits", precision);
+ }
+ p_mpf = QScopy_prob_mpq_mpf (p_mpq, "mpf_problem");
+ if(DEBUG >= __QS_SB_VERB)
+ {
+ EGcallD(mpf_QSwrite_prob(p_mpf, "qsxprob.mpf.lp","LP"));
+ }
+ if(__QS_SB_VERB <= DEBUG) p_mpf->simplex_display = 1;
+ simplexalgo = PRIMAL_SIMPLEX;
+ if(!last_iter) last_status = QS_LP_UNSOLVED;
+ if(last_status == QS_LP_OPTIMAL || last_status == QS_LP_INFEASIBLE)
+ {
+ if (p_mpq->simplex_display || DEBUG >= __QS_SB_VERB)
+ {
+ QSlog("Re-using previous basis");
+ }
+ if (basis)
+ {
+ EGcallD(mpf_QSload_basis (p_mpf, basis));
+ mpf_QSfree_basis (basis);
+ simplexalgo = DUAL_SIMPLEX;
+ basis = 0;
+ }
+ else if (ebasis && ebasis->nstruct)
+ {
+ mpf_QSload_basis (p_mpf, ebasis);
+ simplexalgo = DUAL_SIMPLEX;
+ }
+ }
+ else
+ {
+ if(p_mpf->basis)
+ {
+ mpf_ILLlp_basis_free(p_mpf->basis);
+ p_mpf->lp->basisid = -1;
+ p_mpf->factorok = 0;
+ }
+ if (p_mpq->simplex_display || DEBUG >= __QS_SB_VERB)
+ {
+ QSlog("Not-using previous basis");
+ }
+ }
+ if (mpf_ILLeditor_solve (p_mpf, simplexalgo))
+ {
+ if (p_mpq->simplex_display || DEBUG >= __QS_SB_VERB)
+ {
+ QSlog("mpf_%u precision falied, error code %d, continuing with "
+ "next precision", precision, rval);
+ }
+ goto NEXT_PRECISION;
+ }
+ EGcallD(mpf_QSget_status (p_mpf, status));
+ if ((*status == QS_LP_INFEASIBLE) &&
+ (p_mpf->lp->final_phase != PRIMAL_PHASEI) &&
+ (p_mpf->lp->final_phase != DUAL_PHASEII))
+ mpf_QSopt_primal (p_mpf, status);
+ EGcallD(mpf_QSget_status (p_mpf, status));
+ last_status = *status;
+ EGcallD(mpf_QSget_itcnt(p_mpf, 0, 0, 0, 0, &last_iter));
+ /* deal with the problem depending on status we got from our optimizer */
+ switch (*status)
+ {
+ case QS_LP_OPTIMAL:
+ basis = mpf_QSget_basis (p_mpf);
+ x_mpf = mpf_EGlpNumAllocArray (p_mpf->qslp->ncols);
+ y_mpf = mpf_EGlpNumAllocArray (p_mpf->qslp->nrows);
+ EGcallD(mpf_QSget_x_array (p_mpf, x_mpf));
+ EGcallD(mpf_QSget_pi_array (p_mpf, y_mpf));
+ x_mpq = QScopy_array_mpf_mpq (x_mpf);
+ y_mpq = QScopy_array_mpf_mpq (y_mpf);
+ mpf_EGlpNumFreeArray (x_mpf);
+ mpf_EGlpNumFreeArray (y_mpf);
+ if (QSexact_optimal_test (p_mpq, x_mpq, y_mpq, basis))
+ {
+ optimal_output (p_mpq, x, y, x_mpq, y_mpq);
+ goto CLEANUP;
+ }
+ else
+ {
+ EGcallD(QSexact_basis_status (p_mpq, status, basis, msg_lvl, &simplexalgo));
+ if (*status == QS_LP_OPTIMAL)
+ {
+ MESSAGE (msg_lvl, "Retesting solution");
+ EGcallD(mpq_QSget_x_array (p_mpq, x_mpq));
+ EGcallD(mpq_QSget_pi_array (p_mpq, y_mpq));
+ if (QSexact_optimal_test (p_mpq, x_mpq, y_mpq, basis))
+ {
+ optimal_output (p_mpq, x, y, x_mpq, y_mpq);
+ goto CLEANUP;
+ }
+ else
+ {
+ last_status = *status = QS_LP_UNSOLVED;
+ }
+ }
+ else
+ MESSAGE (msg_lvl, "Status is not optimal, but %d", *status);
+ }
+ mpq_EGlpNumFreeArray (x_mpq);
+ mpq_EGlpNumFreeArray (y_mpq);
+ break;
+ case QS_LP_INFEASIBLE:
+ y_mpf = mpf_EGlpNumAllocArray (p_mpf->qslp->nrows);
+ EGcallD(mpf_QSget_infeas_array (p_mpf, y_mpf));
+ y_mpq = QScopy_array_mpf_mpq (y_mpf);
+ mpf_EGlpNumFreeArray (y_mpf);
+ if (QSexact_infeasible_test (p_mpq, y_mpq))
+ {
+ infeasible_output (p_mpq, y, y_mpq);
+ goto CLEANUP;
+ }
+ else
+ {
+ MESSAGE (msg_lvl, "Retesting solution in exact arithmetic");
+ basis = mpf_QSget_basis (p_mpf);
+ EGcallD(QSexact_basis_status (p_mpq, status, basis, msg_lvl, &simplexalgo));
+#if 0
+ mpq_QSset_param (p_mpq, QS_PARAM_SIMPLEX_MAX_ITERATIONS, 1);
+ mpq_QSload_basis (p_mpq, basis);
+ mpq_QSfree_basis (basis);
+ EGcallD(mpq_ILLeditor_solve (p_mpq, simplexalgo));
+ EGcallD(mpq_QSget_status (p_mpq, status));
+#endif
+ if (*status == QS_LP_INFEASIBLE)
+ {
+ mpq_EGlpNumFreeArray (y_mpq);
+ y_mpq = mpq_EGlpNumAllocArray (p_mpq->qslp->nrows);
+ EGcallD(mpq_QSget_infeas_array (p_mpq, y_mpq));
+ if (QSexact_infeasible_test (p_mpq, y_mpq))
+ {
+ infeasible_output (p_mpq, y, y_mpq);
+ goto CLEANUP;
+ }
+ else
+ {
+ last_status = *status = QS_LP_UNSOLVED;
+ }
+ }
+ }
+ mpq_EGlpNumFreeArray (y_mpq);
+ break;
+ break;
+ case QS_LP_OBJ_LIMIT:
+ rval=1;
+ IFMESSAGE(p_mpq->simplex_display,"Objective limit reached (in floating point) ending now");
+ goto CLEANUP;
+ break;
+ case QS_LP_UNBOUNDED:
+ default:
+ MESSAGE(__QS_SB_VERB,"Re-trying inextended precision");
+ break;
+ }
+ NEXT_PRECISION:
+ mpf_QSfree_prob (p_mpf);
+ p_mpf = 0;
+ }
+ /* ending */
+CLEANUP:
+ dbl_EGlpNumFreeArray (x_dbl);
+ dbl_EGlpNumFreeArray (y_dbl);
+ mpq_EGlpNumFreeArray (x_mpq);
+ mpq_EGlpNumFreeArray (y_mpq);
+ mpf_EGlpNumFreeArray (x_mpf);
+ mpf_EGlpNumFreeArray (y_mpf);
+ if (ebasis && basis)
+ {
+ ILL_IFFREE (ebasis->cstat, char);
+ ILL_IFFREE (ebasis->rstat, char);
+ ebasis->nstruct = basis->nstruct;
+ ebasis->nrows = basis->nrows;
+ ebasis->cstat = basis->cstat;
+ ebasis->rstat = basis->rstat;
+ basis->cstat = basis->rstat = 0;
+ }
+ mpq_QSfree_basis (basis);
+ dbl_QSfree_prob (p_dbl);
+ mpf_QSfree_prob (p_mpf);
+ return rval;
+}
+
+/* ========================================================================= */
+int __QSexact_setup = 0;
+/* ========================================================================= */
+void QSexactStart(void)
+{
+ /* if we have been initialized before, do nothing */
+ if(__QSexact_setup) return;
+ /* we should call EGlpNumStart() */
+ EGlpNumStart();
+ /* now we call all setups */
+ EXutilDoInit();
+ dbl_ILLstart();
+ mpf_ILLstart();
+ mpq_ILLstart();
+ /* ending */
+ __QSexact_setup = 1;
+}
+/* ========================================================================= */
+void QSexactClear(void)
+{
+ if(!__QSexact_setup) return;
+ /* now we call all ends */
+ dbl_ILLend();
+ mpf_ILLend();
+ mpq_ILLend();
+ EXutilDoClear();
+ /* ending */
+ EGlpNumClear();
+ __QSexact_setup = 0;
+}
+/* ========================================================================= */
+/** @} */
+/* end of exact.c */
+
diff --git a/qsopt_ex/exact.h b/qsopt_ex/exact.h
new file mode 100644
index 0000000..b47f72b
--- /dev/null
+++ b/qsopt_ex/exact.h
@@ -0,0 +1,361 @@
+/* ========================================================================= */
+/* ESolver "Exact Mixed Integer Linear Solver" provides some basic structures
+ * and algorithms commons in solving MIP's
+ *
+ * Copyright (C) 2005 Daniel Espinoza.
+ *
+ * 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
+ * */
+/* ========================================================================= */
+#ifndef __EXACT_H__
+#define __EXACT_H__
+
+#include <gmp.h>
+
+#include "basicdefs.h"
+#include "eg_io.h"
+#include "eg_lpnum.h"
+#include "eg_lpnum.dbl.h"
+#include "eg_lpnum.mpq.h"
+#include "eg_lpnum.mpf.h"
+#include "lpdata_dbl.h"
+#include "lpdata_mpq.h"
+#include "lpdata_mpf.h"
+#include "qsopt_mpf.h" /* mpf_QSset_precision */
+#include "qstruct_dbl.h"
+#include "qstruct_mpq.h"
+#include "qstruct_mpf.h"
+
+/* ========================================================================= */
+/** @defgroup Esolver Esolver
+ * Here we define an interface to solve LP's (#QSexact_solver) and MIP's
+ * exactly.
+ * @par History:
+ * Revision 0.1
+ * - 2005-11-14
+ * - Fix handling of infeasibility testing, the problem is that
+ * sometimes, the QSget_infeas_array only work after calling primal
+ * simplex, so, if we are doing dual, ans finish with infeasibility
+ * status, the call will fail, the fix is to call primal simples on
+ * those cases before calling the infeasibility proof.
+ * - 2005-10-05
+ * - If one of the floating point approximations fail, keep going
+ * to the next floating point approximation. A floating point
+ * approximation may fail because the basis is singular within the
+ * used precision.
+ * - 2005-09-29
+ * - If the plain double approximation return unbounded we re-try
+ * in extended precision, but when the extended precision LP solver
+ * return with QS_LP_UNBOUNDED status, we just give-up and return
+ * QS_LP_UNBOUNDED status.
+ * - 2005-08-17
+ * - Improve reliability of optimality test.
+ * - 2005-07-07
+ * - Load optimal soplution into the cache.
+ * - Change the behavior of QSopt, when he wants to re-start simplex,
+ * we instead increase the precision of the numbers, this behavior
+ * is managed by DO_NUMER and DO_SINGULAR.
+ * - 2005-05-31
+ * - If the status of the ending call is not optimal, we don't load
+ * the previous basis, this is because in some examples doing so lead
+ * to bad behavior of the overall code.
+ * - 2005-05-11
+ * - First definition and implementation
+ *
+ * */
+/** @file
+ * @ingroup Esolver */
+/** @addtogroup Esolver */
+/** @{ */
+/* ========================================================================= */
+
+/* ========================================================================= */
+/** @brief If enabled, save the last problem proved to be optimal, and its
+ * solution. */
+#define QSEXACT_SAVE_OPTIMAL 0
+
+/* ========================================================================= */
+/** @brief If enabled, save the intermediate problems created by the functions
+ * #QScopy_prob_mpq_dbl and #QScopy_prob_mpq_mpf */
+#define QSEXACT_SAVE_INT 0
+
+/* ========================================================================= */
+/** @brief Copy an exact problem (mpq_QSdata) to a regular double version of the
+ * problem (dbl_QSdata) */
+dbl_QSdata *QScopy_prob_mpq_dbl (mpq_QSdata * p,
+ const char *newname);
+
+/* ========================================================================= */
+/** @brief Copy an exact problem (mpq_QSdata) to a regular double version of the
+ * problem (dbl_QSdata) */
+mpf_QSdata *QScopy_prob_mpq_mpf (mpq_QSdata * p,
+ const char *newname);
+
+/* ========================================================================= */
+/** @brief Test if a given primal/dual solution is feasible and has the same
+ * objective value.
+ * @param p original problem.
+ * @param p_sol primal solution candidate.
+ * @param d_sol dual solution candidate.
+ * @param basis Basis for wich the current primal/dual vector is a solution.
+ * @return one if the given primal/dual solution is optimal, zero otherwise.
+ * @par Description:
+ * The input problem has the form \f[ \begin{array}{l}\min cx\\
+ s.t. \begin{array}{lcl}Ax&=&b\end{array}\\
+ l\leq x\leq u\end{array} \f]
+ * where some of the bounds can be \f$\infty\f$ or \f$-\infty\f$. Note that from
+ * this the dual problem is allways feasible (we treat \f$\infty\f$ as a
+ * suitable large number) because it looks like
+ * \f[ \begin{array}{l}\max by + d_uu-d_ll\\
+ s.t. \begin{array}{lcl}A^ty-Id_l+Id_u & =& c \end{array}\\
+ d_u,d_l\geq0\end{array} \f] thus we just need to check primal
+ * feasibility and complementary slackness (just to be sure we also check that
+ * both dual and primal objective values coincide.
+ *
+ * If the optimality test is true (i.e. the basis and the given solution, wich
+ * might have been modified inside the function) then this function store the
+ * optimal solution into the cache of the problem.
+ *
+ * @note We assume that p_sol and d_sol have the right size for the problem. and
+ * moreover, we assume that the problem already has the logical variables added
+ * in (to transform it into standard form), this allow us to fix somewhat the
+ * primal vector solution to try to get an optimality certificate.
+ * */
+int QSexact_optimal_test (mpq_QSdata * p,
+ mpq_t * p_sol,
+ mpq_t * d_sol,
+ QSbasis * basis);
+
+/* ========================================================================= */
+/** @brief Print into a file the optimal solution.
+ * @param p original problem.
+ * @param out_f file where to write the solution.
+ * @return zero on success, non-zero otherwise.
+ * */
+int QSexact_print_sol (mpq_QSdata * p,
+ EGioFile_t * out_f);
+
+/* ========================================================================= */
+/** @brief Check if the given dual vector is a proof of infeasibility for the
+ * given exact problem.
+ * @param p pointer to the problem data structure.
+ * @param d_sol array of length at least nrows with the suposed proof of
+ * infeasibility.
+ * @return zero if the given dual vector is indeed a proof of infeasibility for
+ * the problem, non zero otherwise.
+ * @par Description:
+ * Note that for infeasibility, we just need to proof that the problem
+ \f[ \begin{array}{ll} \min & 0\\ s.t. & Ax = b\\ & l\leq x\leq b\\
+ \end{array} \f]
+ * is infeasible, but it's dual is
+ \f[ \begin{array}{ll} \max & by - ud_u + ld_l\\ s.t. & A^ty +Id_l - Id_u = 0\\
+ & d_u,d_l\geq0\\ \end{array} \f]
+ * wich is always feasible (provided \f$y\geq0\f$ (set \f$ (y,d_u,d_l)=0\f$),
+ * and thus we just need to check whether the objective value is \f$\neq 0\f$
+ * and we have a proof of infeasibility for the primal. That's what this
+ * function perform as a test.
+ * */
+int QSexact_infeasible_test (mpq_QSdata * p,
+ mpq_t * d_sol);
+
+/* ========================================================================= */
+/** @brief create a copy of a mpq_t array into a double array.
+ * @param array mpq_t array from where we will create the values. */
+#define QScopy_array_mpq_dbl(array) ({ \
+ mpq_t*__larray = (array);\
+ register unsigned __lsz = __EGlpNumArraySize(__larray);\
+ double*__lres = dbl_EGlpNumAllocArray(__lsz);\
+ while(__lsz--)\
+ {\
+ if(mpq_equal(__larray[__lsz],mpq_ILL_MAXDOUBLE))\
+ __lres[__lsz] = dbl_ILL_MAXDOUBLE;\
+ else if(mpq_equal(__larray[__lsz],mpq_ILL_MINDOUBLE))\
+ __lres[__lsz] = dbl_ILL_MINDOUBLE;\
+ else __lres[__lsz] = mpq_get_d(__larray[__lsz]);\
+ }\
+ __lres;})
+
+/* ========================================================================= */
+/** @brief create a copy of a mpq_t array into a mpf_t array.
+ * @param array mpq_t array from where we will create the values. */
+#define QScopy_array_mpq_mpf(array) ({ \
+ mpq_t*__larray = (array);\
+ register unsigned __lsz = __EGlpNumArraySize(__larray);\
+ mpf_t*__lres = mpf_EGlpNumAllocArray(__lsz);\
+ while(__lsz--)\
+ {\
+ if(mpq_equal(__larray[__lsz],mpq_ILL_MAXDOUBLE))\
+ mpf_set(__lres[__lsz], mpf_ILL_MAXDOUBLE);\
+ else if(mpq_equal(__larray[__lsz],mpq_ILL_MINDOUBLE))\
+ mpf_set(__lres[__lsz], mpf_ILL_MINDOUBLE);\
+ else mpf_set_q(__lres[__lsz],__larray[__lsz]);\
+ }\
+ __lres;})
+
+/* ========================================================================= */
+/** @brief create a copy of a double array into mpq_t array.
+ * @param array original array of double values (note that this array must have
+ * been allocated with dbl_EGlpNumAllocArray for this function to work). */
+#define QScopy_array_dbl_mpq(array) ({ \
+ double*__larray = (array);\
+ register unsigned __lsz = __EGlpNumArraySize(__larray);\
+ mpq_t*__lres = mpq_EGlpNumAllocArray(__lsz);\
+ while(__lsz--)\
+ {\
+ if(__larray[__lsz] == dbl_ILL_MAXDOUBLE)\
+ mpq_set(__lres[__lsz],mpq_ILL_MAXDOUBLE);\
+ else if(__larray[__lsz] == dbl_ILL_MINDOUBLE)\
+ mpq_set(__lres[__lsz],mpq_ILL_MINDOUBLE);\
+ else mpq_EGlpNumSet(__lres[__lsz],__larray[__lsz]);\
+ }\
+ __lres;})
+
+/* ========================================================================= */
+/** @brief create a copy of a mpf_t array into mpq_t array.
+ * @param array original array of double values (note that this array must have
+ * been allocated with __EGlpNumAllocArray for this function to work). */
+#define QScopy_array_mpf_mpq(array) ({ \
+ mpf_t*__larray = (array);\
+ register unsigned __lsz = __EGlpNumArraySize(__larray);\
+ mpq_t*__lres = mpq_EGlpNumAllocArray(__lsz);\
+ while(__lsz--)\
+ {\
+ if(mpf_cmp(__larray[__lsz],mpf_ILL_MAXDOUBLE)==0)\
+ mpq_set(__lres[__lsz],mpq_ILL_MAXDOUBLE);\
+ else if(mpf_cmp(__larray[__lsz],mpf_ILL_MINDOUBLE)==0)\
+ mpq_set(__lres[__lsz],mpq_ILL_MINDOUBLE);\
+ mpq_set_f(__lres[__lsz],__larray[__lsz]);\
+ }\
+ __lres;})
+
+/* ========================================================================= */
+/** @brief Write a given row from the LP into the given stream, in exact
+ * arithmetic */
+void QSexact_write_row (EGioFile_t * out_f,
+ mpq_ILLlpdata * lp,
+ int row);
+
+/* ========================================================================= */
+/** @brief Set the number of bits to use with mpf_t type numbers and change all
+ * internal constants as needed. */
+#define QSexact_set_precision(precision) mpf_QSset_precision(precision)
+
+#ifndef QS_EXACT_MAX_ITER
+/* ========================================================================= */
+/** @brief This constant define the maximum number of try's for the exact solver
+ * with mpf_t numbers while incrementing the precision */
+#define QS_EXACT_MAX_ITER 12
+#endif
+
+/* ========================================================================= */
+/** @brief test whether given basis is primal and dual feasible in rational arithmetic.
+ * @param p_mpq the problem data.
+ * @param basis basis to be tested.
+ * @param result where to store whether given basis is primal and dual feasible.
+ * @param msg_lvl message level.
+ */
+int QSexact_basis_optimalstatus(
+ mpq_QSdata * p_mpq,
+ QSbasis* basis,
+ char* result,
+ const int msg_lvl
+ );
+
+/* ========================================================================= */
+/** @brief test whether given basis is dual feasible in rational arithmetic.
+ * @param p_mpq the problem data.
+ * @param basis basis to be tested.
+ * @param result where to store whether given basis is dual feasible.
+ * @param dobjval where to store dual solution value in case of dual feasibility (if not NULL).
+ * @param msg_lvl message level.
+ */
+int QSexact_basis_dualstatus(
+ mpq_QSdata * p_mpq,
+ QSbasis* basis,
+ char* result,
+ mpq_t* dobjval,
+ const int msg_lvl
+ );
+
+/* ========================================================================= */
+/** @brief test whether given basis is dual feasible in rational arithmetic.
+ * if wanted it will first directly test the corresponding approximate dual and primal solution
+ * (corrected via dual variables for bounds and primal variables for slacks if possible) for optimality
+ * before performing the dual feasibility test on the more expensive exact basic solution.
+ * @param p_mpq the problem data.
+ * @param basis basis to be tested.
+ * @param useprestep whether to directly test approximate primal and dual solution first.
+ * @param dbl_p_sol approximate primal solution to use in prestep
+ * (NULL in order to compute it by dual simplex in double precision with given starting basis).
+ * @param dbl_d_sol approximate dual solution to use in prestep
+ * (NULL in order to compute it by dual simplex in double precision with given starting basis).
+ * @param result where to store whether given basis is dual feasible.
+ * @param dobjval where to store dual solution value in case of dual feasibility (if not NULL).
+ * @param msg_lvl message level.
+ */
+int QSexact_verify (
+ mpq_QSdata * p_mpq,
+ QSbasis* basis,
+ int useprestep,
+ double* dbl_p_sol,
+ double* dbl_d_sol,
+ char* result,
+ mpq_t* dobjval,
+ const int msg_lvl
+ );
+
+/* ========================================================================= */
+/** @brief Given an mpq_QSdata problem, solve it exactly.
+ * @param x if not null, we store here the primal solution to the
+ * problem (if it exist).
+ * @param y if not null, we store here the dual solution to the
+ * problem,
+ * @param p_mpq problem to solve exactly.
+ * @param status pointer to the integer where we will return the status
+ * of the problem, either optimal, infeasible, or unbounded (we could also
+ * return time out).
+ * @param simplexalgo whether to use primal or dual simplex while solving
+ * to optimality the problem.
+ * @param basis if not null, use the given basis to start the
+ * iteration of simplex, and store here the optimal basis (if found).
+ * @return zero on success, non-zero otherwise. */
+int QSexact_solver (mpq_QSdata * p_mpq,
+ mpq_t * const x,
+ mpq_t * const y,
+ QSbasis * const basis,
+ int simplexalgo,
+ int *status);
+
+/* ========================================================================= */
+/** @brief Initializator for global data, this is needed mainly for defining
+ * constants in extended floating point precision and for rational precision.
+ * This call should be done BEFORE any mpq_xxx mpf_xxx QSxx EGxx call */
+extern void QSexactStart(void);
+/* ========================================================================= */
+/** @brief This function must be called at the end of the program to free all
+ * internal data used in the QSexact structures, once this function is called
+ * any operation on EGxxx mpq_xxx mpf_xx QSxx may fail.
+ * */
+extern void QSexactClear(void);
+/* ========================================================================= */
+/** @brief indicate if the global data needed for QSexact has been initialized,
+ * if zero, initialization routine should be called. This is provided to allow
+ * syncronization between libraries */
+extern int __QSexact_setup;
+/** @} */
+/* ========================================================================= */
+/* end of exact.h */
+#endif
+
diff --git a/qsopt_ex/except.c b/qsopt_ex/except.c
new file mode 100644
index 0000000..9f33732
--- /dev/null
+++ b/qsopt_ex/except.c
@@ -0,0 +1,54 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCSINFO $Id: exception.c,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+#include <stdio.h>
+#include <string.h>
+
+#include "except.h"
+
+#include "logging-private.h"
+
+
+void ILL_report (
+ const char *msg,
+ const char *fct,
+ const char *file,
+ unsigned int line,
+ int with_src_info)
+{
+ if (msg != NULL)
+ {
+ QSlog("FAILURE: %s", msg);
+ if (with_src_info == 1)
+ {
+ if (fct != NULL)
+ {
+ QSlog("\tin function %s", fct);
+ }
+ QSlog("\tin file %s line %d", file, line);
+ }
+ }
+}
+
+/* by default we turn off verbose messages of singular basis */
+int __QS_SB_VERB = 1000;
diff --git a/qsopt_ex/except.h b/qsopt_ex/except.h
new file mode 100644
index 0000000..138371c
--- /dev/null
+++ b/qsopt_ex/except.h
@@ -0,0 +1,170 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCSINFO $Id: except.h,v 1.3 2003/11/05 17:02:10 meven Exp $ */
+#ifndef ILL_except
+#define ILL_except
+
+#include "allocrus.h"
+#include "trace.h"
+
+/* Version 2.4 and later of GCC define a magical variable `__PRETTY_FUNCTION__'
+ which contains the name of the function currently being defined.
+# define __DEV_FUNCTION__ __PRETTY_FUNCTION__
+ This is broken in G++ before version 2.6.
+ C9x has a similar variable called __func__, but prefer the GCC one since
+ it demangles C++ function names. */
+# ifdef __GNUC__
+# if __GNUC__ > 2 || (__GNUC__ == 2 \
+ && __GNUC_MINOR__ >= (defined __cplusplus ? 6 : 4))
+# define __DEV_FUNCTION__ __PRETTY_FUNCTION__
+# else
+# define __DEV_FUNCTION__ ((__const char *) 0)
+# endif
+# else
+# if defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L
+# define __DEV_FUNCTION__ __func__
+# else
+# define __DEV_FUNCTION__ ((const char *) 0)
+# endif
+# endif
+
+
+/* put debugger breakpoint here */
+extern void ILL_report (
+ const char *msg,
+ const char *fct,
+ const char *file,
+ unsigned int line,
+ int with_source_info);
+
+/* printed message looks as follows
+ *
+ * with_source_info == 0: <msg> + "\n"
+ *
+ * with_source_info == 1: if (fct != NULL)
+ * <msg> + " in function <fct>\n";
+ * else
+ * <msg> + " in file <file> line <line>\n";
+ */
+
+#define ILL_GENERAL_ERROR -1
+#define ILL_NO_MEMORY 2
+#define ILL_NULL_PTR 3
+
+#define ILL_REPORT(msg,with) \
+ ILL_report(msg, __DEV_FUNCTION__, __FILE__, __LINE__, with)
+#ifdef NDEBUG
+#define ILL_REPRT(msg) \
+ ILL_report(msg, __DEV_FUNCTION__, __FILE__, __LINE__, 0)
+#else
+#define ILL_REPRT(msg) \
+ ILL_report(msg, __DEV_FUNCTION__, __FILE__, __LINE__, 1)
+#endif
+
+#define ILL_RESULT(expr, msg) \
+{ \
+ if (TRACE > 0) { ILL_RETURN(expr, msg); } \
+ return expr; \
+}
+
+#define ILL_RETURN_PTR(ptr, msg) \
+ { void *ILL_RETURN_p = ptr; \
+ if (ILL_RETURN_p == NULL) { \
+ if (TRACE > 0) ILL_REPRT(msg); \
+ } \
+ return ILL_RETURN_p; \
+ }
+
+#ifdef NDEBUG
+#define ILL_RETURN(expr, msg) \
+{ \
+ if (expr != 0) { \
+ if (TRACE > 0) ILL_REPRT(msg); \
+ } \
+ return expr; \
+}
+
+#else
+#define ILL_RETURN(expr, msg) \
+ { \
+ if (expr != 0) { \
+ ILL_REPRT(msg); \
+ } \
+ ILL_IFTRACE("%s: returning %d\n", __DEV_FUNCTION__, expr); \
+ return expr; \
+ }
+#endif
+
+#define ILL_CHECKnull(expr, msg) \
+ { if ((expr) == NULL) { \
+ ILL_REPRT(msg); \
+ rval = ILL_NULL_PTR; \
+ goto CLEANUP; \
+ } }
+
+#define ILL_FAILtrue(expr, msg) \
+ { if (expr) { \
+ ILL_REPRT(msg); \
+ rval = ILL_GENERAL_ERROR; \
+ goto CLEANUP; \
+ } }
+
+#define ILL_FAILtrue_no_rval(expr, msg) \
+ { if (expr) { \
+ ILL_REPRT(msg); \
+ goto CLEANUP; \
+ } }
+
+
+#define ILL_FAILfalse(expr, msg) ILL_FAILtrue(!(expr), msg)
+#define ILL_FAILfalse_no_rval(expr, msg) ILL_FAILtrue_no_rval(!(expr), msg)
+
+#define ILL_ERROR(rval, msg) { \
+ fprintf(stderr, "%s\n", msg); \
+ rval = 1; goto CLEANUP; \
+ }
+#define ILL_CLEANUP_IF(rval) { if ((rval) != 0) { goto CLEANUP; } }
+#define ILL_CLEANUP goto CLEANUP
+
+#define ILL_SAFE_MALLOC(lhs, n, type) \
+ { lhs = ILL_UTIL_SAFE_MALLOC(n, type, lhs); \
+ if (lhs == NULL) { \
+ ILL_REPRT("Out of memory"); \
+ rval = ILL_NO_MEMORY; \
+ goto CLEANUP; \
+ }}
+
+#define ILL_SAFE_MALLOC_no_rval(lhs, n, type) \
+ { lhs = ILL_UTIL_SAFE_MALLOC(n, type, lhs); \
+ if (lhs == NULL) { \
+ ILL_REPRT("Out of memory"); \
+ goto CLEANUP; \
+ }}
+
+
+#define ILL_NEW(ptr, type) ILL_SAFE_MALLOC(ptr, 1, type)
+#define ILL_NEW_no_rval(ptr, type) ILL_SAFE_MALLOC_no_rval(ptr, 1, type)
+
+/* we define debugging verbosity for singular basis */
+extern int __QS_SB_VERB;
+#endif
diff --git a/qsopt_ex/factor.c b/qsopt_ex/factor.c
new file mode 100644
index 0000000..98f1473
--- /dev/null
+++ b/qsopt_ex/factor.c
@@ -0,0 +1,5602 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: factor.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+//static int TRACE = 0;
+
+/* implement a = max(a,abs(b)) and execute the extra code if the update is
+ * needed */
+#define EGlpNumSetToMaxAbsAndDo(a,b,c) \
+ if(EGLPNUM_TYPENAME_EGlpNumIsGreatZero(b))\
+ {\
+ if(EGLPNUM_TYPENAME_EGlpNumIsLess(a,b)){\
+ EGLPNUM_TYPENAME_EGlpNumCopy(a,b);\
+ c;\
+ }\
+ }\
+ else\
+ {\
+ EGLPNUM_TYPENAME_EGlpNumSign(a);\
+ if(EGLPNUM_TYPENAME_EGlpNumIsLess(b,a)){\
+ EGLPNUM_TYPENAME_EGlpNumCopy(a,b);\
+ c;\
+ }\
+ EGLPNUM_TYPENAME_EGlpNumSign(a);\
+ }
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+
+#include "logging-private.h"
+
+#include "allocrus.h"
+#include "eg_lpnum.h"
+#include "eg_numutil_EGLPNUM_TYPENAME.h"
+#include "eg_io.h"
+#include "except.h"
+#include "util.h"
+
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+#include "factor_EGLPNUM_TYPENAME.h"
+
+
+#undef RECORD
+#undef DEBUG_FACTOR
+#undef SOLVE_DEBUG
+
+#undef FACTOR_DEBUG
+#undef UPDATE_DEBUG
+
+#undef TRACK_FACTOR
+#undef NOTICE_BLOWUP
+
+#undef FACTOR_STATS
+#undef UPDATE_STATS
+#undef GROWTH_STATS
+
+#undef UPDATE_STUDY
+
+#undef SORT_RESULTS
+
+#ifdef UPDATE_STUDY
+int nupdate = 0;
+long int colspiketot = 0.0;
+long int rowspiketot = 0.0;
+long int permshifttot = 0.0;
+long int leftetatot = 0.0;
+#endif
+
+void EGLPNUM_TYPENAME_ILLfactor_init_factor_work (
+ EGLPNUM_TYPENAME_factor_work * f)
+{
+ f->max_k = 1000; /* must be less than 46340 (2^15.5) */
+ EGLPNUM_TYPENAME_EGlpNumCopy (f->fzero_tol, EGLPNUM_TYPENAME_SZERO_TOLER); /* 2^-50 */
+ EGLPNUM_TYPENAME_EGlpNumCopy (f->szero_tol, EGLPNUM_TYPENAME_SZERO_TOLER); /* 2^-50 */
+ EGLPNUM_TYPENAME_EGlpNumCopy (f->partial_tol, EGLPNUM_TYPENAME_OBJBND_TOLER); /* 2^-7 */
+ f->ur_space_mul = 2.0;
+ f->uc_space_mul = 1.1;
+ f->lc_space_mul = 1.1;
+ f->er_space_mul = 1000.0;
+ f->grow_mul = 1.5;
+ f->p = 4;
+ f->etamax = 100;
+ f->minmult = 1e3;
+ f->maxmult = 1e5;
+ f->updmaxmult = 1e7;
+ f->dense_fract = 0.25;
+ f->dense_min = 25;
+ EGLPNUM_TYPENAME_EGlpNumCopy (f->partial_cur, f->partial_tol);
+ f->work_coef = 0;
+ f->work_indx = 0;
+ f->uc_inf = 0;
+ f->ur_inf = 0;
+ f->lc_inf = 0;
+ f->lr_inf = 0;
+ f->er_inf = 0;
+ f->ucindx = 0;
+ f->ucrind = 0;
+ f->uccoef = 0;
+ f->urindx = 0;
+ f->urcind = 0;
+ f->urcoef = 0;
+ f->lcindx = 0;
+ f->lccoef = 0;
+ f->lrindx = 0;
+ f->lrcoef = 0;
+ f->erindx = 0;
+ f->ercoef = 0;
+ f->rperm = 0;
+ f->rrank = 0;
+ f->cperm = 0;
+ f->crank = 0;
+ f->dmat = 0;
+ EGLPNUM_TYPENAME_ILLsvector_init (&f->xtmp);
+}
+
+void EGLPNUM_TYPENAME_ILLfactor_free_factor_work (
+ EGLPNUM_TYPENAME_factor_work * f)
+{
+#ifdef UPDATE_STUDY
+ if (nupdate)
+ {
+ MESSAGE(0, "UPDATE STUDY: avg %d upd: %.2f col, %.2f row, %.2f lefteta, "
+ "%.2f perm", nupdate, ((double) colspiketot) / nupdate,
+ ((double) rowspiketot) / nupdate, ((double) leftetatot) / nupdate,
+ ((double) permshifttot) / nupdate);
+ }
+#endif
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (f->work_coef);
+ ILL_IFFREE (f->work_indx, int);
+
+ ILL_IFFREE (f->uc_inf, EGLPNUM_TYPENAME_uc_info);
+ if (f->dim + f->max_k > 0 && f->ur_inf)
+ {
+ unsigned int i = f->dim + f->max_k + 1;
+
+ while (i--)
+ EGLPNUM_TYPENAME_EGlpNumClearVar (f->ur_inf[i].max);
+ }
+ ILL_IFFREE (f->ur_inf, EGLPNUM_TYPENAME_ur_info);
+ ILL_IFFREE (f->lc_inf, EGLPNUM_TYPENAME_lc_info);
+ ILL_IFFREE (f->lr_inf, EGLPNUM_TYPENAME_lr_info);
+ ILL_IFFREE (f->er_inf, EGLPNUM_TYPENAME_er_info);
+ ILL_IFFREE (f->ucindx, int);
+ ILL_IFFREE (f->ucrind, int);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (f->uccoef);
+ ILL_IFFREE (f->urindx, int);
+ ILL_IFFREE (f->urcind, int);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (f->urcoef);
+ ILL_IFFREE (f->lcindx, int);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (f->lccoef);
+ ILL_IFFREE (f->lrindx, int);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (f->lrcoef);
+ ILL_IFFREE (f->erindx, int);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (f->ercoef);
+ ILL_IFFREE (f->rperm, int);
+ ILL_IFFREE (f->rrank, int);
+ ILL_IFFREE (f->cperm, int);
+ ILL_IFFREE (f->crank, int);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (f->dmat);
+ EGLPNUM_TYPENAME_ILLsvector_free (&f->xtmp);
+}
+
+int EGLPNUM_TYPENAME_ILLfactor_set_factor_iparam (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int param,
+ int val)
+{
+ switch (param)
+ {
+ case QS_FACTOR_MAX_K:
+ f->max_k = val;
+ break;
+ case QS_FACTOR_P:
+ f->p = val;
+ break;
+ case QS_FACTOR_ETAMAX:
+ f->etamax = val;
+ break;
+ case QS_FACTOR_DENSE_MIN:
+ f->dense_min = val;
+ break;
+ default:
+ QSlog("Invalid param %d in EGLPNUM_TYPENAME_ILLfactor_set_factor_iparam",
+ param);
+ return 1;
+ }
+ return 0;
+}
+
+int EGLPNUM_TYPENAME_ILLfactor_set_factor_dparam (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int param,
+ EGLPNUM_TYPE val)
+{
+ switch (param)
+ {
+ case QS_FACTOR_FZERO_TOL:
+ EGLPNUM_TYPENAME_EGlpNumCopy (f->fzero_tol, val);
+ break;
+ case QS_FACTOR_SZERO_TOL:
+ EGLPNUM_TYPENAME_EGlpNumCopy (f->szero_tol, val);
+ break;
+ case QS_FACTOR_UR_SPACE_MUL:
+ f->ur_space_mul = EGLPNUM_TYPENAME_EGlpNumToLf (val);
+ break;
+ case QS_FACTOR_UC_SPACE_MUL:
+ f->uc_space_mul = EGLPNUM_TYPENAME_EGlpNumToLf (val);
+ break;
+ case QS_FACTOR_LC_SPACE_MUL:
+ f->lc_space_mul = EGLPNUM_TYPENAME_EGlpNumToLf (val);
+ break;
+ case QS_FACTOR_LR_SPACE_MUL:
+ f->lr_space_mul = EGLPNUM_TYPENAME_EGlpNumToLf (val);
+ break;
+ case QS_FACTOR_ER_SPACE_MUL:
+ f->er_space_mul = EGLPNUM_TYPENAME_EGlpNumToLf (val);
+ break;
+ case QS_FACTOR_GROW_MUL:
+ f->grow_mul = EGLPNUM_TYPENAME_EGlpNumToLf (val);
+ break;
+ case QS_FACTOR_MAXMULT:
+ f->maxmult = EGLPNUM_TYPENAME_EGlpNumToLf (val);
+ break;
+ case QS_FACTOR_UPDMAXMULT:
+ f->updmaxmult = EGLPNUM_TYPENAME_EGlpNumToLf (val);
+ break;
+ case QS_FACTOR_DENSE_FRACT:
+ f->dense_fract = EGLPNUM_TYPENAME_EGlpNumToLf (val);
+ break;
+ case QS_FACTOR_PARTIAL_TOL:
+ EGLPNUM_TYPENAME_EGlpNumCopy (f->partial_tol, val);
+ EGLPNUM_TYPENAME_EGlpNumCopy (f->partial_cur, val);
+ break;
+ default:
+ QSlog("Invalid param %d in EGLPNUM_TYPENAME_ILLfactor_set_factor_dparam",
+ param);
+ return 1;
+ }
+ return 0;
+}
+
+int EGLPNUM_TYPENAME_ILLfactor_create_factor_work (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int dim)
+{
+ int i;
+ int rval;
+
+ f->dim = dim;
+ f->etacnt = 0;
+ f->work_coef = EGLPNUM_TYPENAME_EGlpNumAllocArray (dim);
+ ILL_SAFE_MALLOC (f->work_indx, dim, int);
+
+ ILL_SAFE_MALLOC (f->uc_inf, dim + (f->max_k + 1), EGLPNUM_TYPENAME_uc_info);
+ ILL_SAFE_MALLOC (f->ur_inf, dim + (f->max_k + 1), EGLPNUM_TYPENAME_ur_info);
+ ILL_SAFE_MALLOC (f->lc_inf, dim, EGLPNUM_TYPENAME_lc_info);
+ ILL_SAFE_MALLOC (f->lr_inf, dim, EGLPNUM_TYPENAME_lr_info);
+ ILL_SAFE_MALLOC (f->rperm, dim, int);
+ ILL_SAFE_MALLOC (f->rrank, dim, int);
+ ILL_SAFE_MALLOC (f->cperm, dim, int);
+ ILL_SAFE_MALLOC (f->crank, dim, int);
+
+ for (i = dim + f->max_k + 1; i--;)
+ EGLPNUM_TYPENAME_EGlpNumInitVar (f->ur_inf[i].max);
+
+ for (i = 0; i < dim; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumZero (f->work_coef[i]);
+ f->work_indx[i] = 0;
+ f->uc_inf[i].nzcnt = 0;
+ f->ur_inf[i].nzcnt = 0;
+ f->lc_inf[i].nzcnt = 0;
+ f->lr_inf[i].nzcnt = 0;
+ f->rperm[i] = i;
+ f->rrank[i] = i;
+ f->cperm[i] = i;
+ f->crank[i] = i;
+ }
+ for (i = 0; i <= f->max_k; i++)
+ {
+ f->uc_inf[dim + i].nzcnt = i;
+ f->uc_inf[dim + i].next = dim + i;
+ f->uc_inf[dim + i].prev = dim + i;
+ f->ur_inf[dim + i].nzcnt = i;
+ f->ur_inf[dim + i].next = dim + i;
+ f->ur_inf[dim + i].prev = dim + i;
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&f->xtmp, dim);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = 0;
+
+CLEANUP:
+ if (rval)
+ {
+ EGLPNUM_TYPENAME_ILLfactor_free_factor_work (f);
+ }
+ EG_RETURN (rval);
+}
+#ifdef FACTOR_DEBUG
+static void dump_matrix (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int remaining)
+{
+ int dim = f->dim;
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+ EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+ EGLPNUM_TYPENAME_lc_info *lc_inf = f->lc_inf;
+ EGLPNUM_TYPENAME_lr_info *lr_inf = f->lr_inf;
+ EGLPNUM_TYPENAME_er_info *er_inf = f->er_inf;
+ int nzcnt;
+ int beg;
+
+ int i;
+ int j;
+
+ for (i = 0; i < dim; i++)
+ {
+ if (!remaining || ur_inf[i].next >= 0)
+ {
+ QSlog("Row %d %d (max %.3f):", i, f->rrank[i],
+ EGLPNUM_TYPENAME_EGlpNumToLf (ur_inf[i].max));
+ nzcnt = ur_inf[i].nzcnt;
+ beg = ur_inf[i].rbeg;
+ for (j = 0; j < nzcnt; j++)
+ {
+ if (j == ur_inf[i].pivcnt)
+ {
+ QSlog(" |");
+ }
+ QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (f->urcoef[beg + j]),
+ f->urindx[beg + j]);
+ if (f->urcind)
+ QSlog("@%d", f->urcind[beg + j]);
+ }
+ }
+ }
+ if (f->dmat)
+ {
+ int start = 0;
+
+ if (remaining)
+ start = f->stage - f->dense_base;
+ QSlog("Dcols at %d %d - %d :", f->stage - f->dense_base,
+ f->dense_base + start, f->nstages);
+ for (j = start; j < f->dcols; j++)
+ {
+ QSlog(" %5d", f->cperm[j + f->dense_base]);
+ }
+
+ for (i = start; i < f->drows; i++)
+ {
+ QSlog("DRow %d %d (max %.3f):", i,
+ f->rperm[i + f->dense_base],
+ EGLPNUM_TYPENAME_EGlpNumToLf (ur_inf[f->rperm[i + f->dense_base]].max));
+ for (j = start; j < f->dcols; j++)
+ {
+ if (j == f->drows)
+ {
+ QSlog(" |");
+ }
+ QSlog(" %.3f", EGLPNUM_TYPENAME_EGlpNumToLf (f->dmat[i * f->dcols + j]));
+ }
+ }
+ }
+
+ if (!remaining)
+ {
+ for (i = 0; i < f->stage; i++)
+ {
+ QSlog("L col %d:", lc_inf[i].c);
+ nzcnt = lc_inf[i].nzcnt;
+ beg = lc_inf[i].cbeg;
+ for (j = 0; j < nzcnt; j++)
+ {
+ QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (f->lccoef[beg + j]),
+ f->lcindx[beg + j]);
+ }
+ }
+ for (i = f->nstages; i < f->dim; i++)
+ {
+ QSlog("L col %d:", lc_inf[i].c);
+ nzcnt = lc_inf[i].nzcnt;
+ beg = lc_inf[i].cbeg;
+ for (j = 0; j < nzcnt; j++)
+ {
+ QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (f->lccoef[beg + j]),
+ f->lcindx[beg + j]);
+ }
+ }
+ for (i = 0; i < f->dim; i++)
+ {
+ if (!lr_inf[i].nzcnt)
+ continue;
+ QSlog("L row %d:", lr_inf[i].r);
+ nzcnt = lr_inf[i].nzcnt;
+ beg = lr_inf[i].rbeg;
+ for (j = 0; j < nzcnt; j++)
+ {
+ QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (f->lrcoef[beg + j]),
+ f->lrindx[beg + j]);
+ }
+ }
+ }
+
+ if (!remaining)
+ {
+ for (i = 0; i < f->etacnt; i++)
+ {
+ QSlog("Eta row %d:", f->er_inf[i].r);
+ nzcnt = er_inf[i].nzcnt;
+ beg = er_inf[i].rbeg;
+ for (j = 0; j < nzcnt; j++)
+ {
+ QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (f->ercoef[beg + j]),
+ f->erindx[beg + j]);
+ }
+ }
+ }
+
+ for (i = 0; i < dim; i++)
+ {
+ if (!remaining || uc_inf[i].next >= 0)
+ {
+ QSlog("Col %d %d:", i, f->crank[i]);
+ nzcnt = uc_inf[i].nzcnt;
+ beg = uc_inf[i].cbeg;
+ for (j = 0; j < nzcnt; j++)
+ {
+ if (f->uccoef != 0)
+ {
+ QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (f->uccoef[beg + j]),
+ f->ucindx[beg + j]);
+ if (f->ucrind)
+ QSlog("@%d", f->ucrind[beg + j]);
+ }
+ else
+ {
+ QSlog(" %d", f->ucindx[beg + j]);
+ }
+ }
+ }
+ }
+
+ if (!remaining)
+ {
+ QSlog("rperm:");
+ for (i = 0; i < dim; i++)
+ {
+ if (i == f->nstages)
+ QSlog("|");
+ if (i == f->stage)
+ QSlog("|");
+ QSlog(" %d", f->rperm[i]);
+ }
+
+ QSlog("cperm:");
+ for (i = 0; i < dim; i++)
+ {
+ if (i == f->nstages)
+ QSlog("|");
+ if (i == f->stage)
+ QSlog("|");
+ QSlog(" %d", f->cperm[i]);
+ }
+ }
+
+ QSlog("Rows by nzcnt:");
+ for (i = 0; i <= f->max_k; i++)
+ {
+ if (ur_inf[dim + i].next != dim + i)
+ {
+ QSlog("%d:", i);
+ for (j = ur_inf[dim + i].next; j != dim + i; j = ur_inf[j].next)
+ {
+ QSlog(" %d", j);
+ }
+ }
+ }
+
+ QSlog("Cols by nzcnt:\n");
+ for (i = 0; i <= f->max_k; i++)
+ {
+ if (uc_inf[dim + i].next != dim + i)
+ {
+ QSlog("%d:", i);
+ for (j = uc_inf[dim + i].next; j != dim + i; j = uc_inf[j].next)
+ {
+ QSlog(" %d", j);
+ }
+ }
+ }
+}
+#endif
+
+#ifdef SORT_RESULTS
+static void sort_vector2 (
+ int nzcnt,
+ int *indx,
+ EGLPNUM_TYPE * coef)
+{
+ int i;
+ int j;
+ int itmp;
+ EGLPNUM_TYPE ctmp;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (ctmp);
+
+ for (i = 1; i < nzcnt; i++)
+ {
+ itmp = indx[i];
+ EGLPNUM_TYPENAME_EGlpNumCopy (ctmp, coef[i]);
+ for (j = i; j >= 1 && indx[j - 1] > itmp; j--)
+ {
+ indx[j] = indx[j - 1];
+ EGLPNUM_TYPENAME_EGlpNumCopy (coef[j], coef[j - 1]);
+ }
+ indx[j] = itmp;
+ EGLPNUM_TYPENAME_EGlpNumCopy (coef[j], ctmp);
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ctmp);
+}
+
+static void sort_vector (
+ EGLPNUM_TYPENAME_svector * x)
+{
+ sort_vector2 (x->nzcnt, x->indx, x->coef);
+}
+#endif
+
+#ifdef DEBUG_FACTOR
+static int check_matrix (
+ EGLPNUM_TYPENAME_factor_work * f)
+{
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+ EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+ int rbeg;
+ int nzcnt;
+ int cbeg;
+ int c;
+ int r;
+ int j;
+ int nerr = 0;
+
+ for (r = 0; r < f->dim; r++)
+ {
+ nzcnt = ur_inf[r].nzcnt;
+ rbeg = ur_inf[r].rbeg;
+ for (j = 0; j < nzcnt; j++)
+ {
+ c = f->urindx[rbeg + j];
+ cbeg = uc_inf[c].cbeg;
+ if (f->ucindx[cbeg + f->urcind[rbeg + j]] != r)
+ {
+ MESSAGE(0,"index mismatch, row %d column %d", r, c);
+ nerr++;
+ }
+ if (fabs(EGLPNUM_TYPENAME_EGlpNumToLf(f->uccoef[cbeg + f->urcind[rbeg + j]]) - EGLPNUM_TYPENAME_EGlpNumToLf(f->urcoef[rbeg + j]))>1000*EGLPNUM_TYPENAME_EGlpNumToLf(EGLPNUM_TYPENAME_epsLpNum))
+ {
+ MESSAGE(0,"coef mismatch, row %d column %d", r, c);
+ nerr++;
+ }
+ }
+ }
+ if (f->urindx[f->ur_space] != 0)
+ {
+ MESSAGE(0,"last urindx entry %d != 0", f->urindx[f->ur_space]);
+ nerr++;
+ }
+
+ for (c = 0; c < f->dim; c++)
+ {
+ nzcnt = uc_inf[c].nzcnt;
+ cbeg = uc_inf[c].cbeg;
+ for (j = 0; j < nzcnt; j++)
+ {
+ r = f->ucindx[cbeg + j];
+ rbeg = ur_inf[r].rbeg;
+ if (f->urindx[rbeg + f->ucrind[cbeg + j]] != c)
+ {
+ MESSAGE(0,"index mismatch, column %d row %d", c, r);
+ nerr++;
+ }
+ if (f->urcoef[rbeg + f->ucrind[cbeg + j]] != f->uccoef[cbeg + j])
+ {
+ MESSAGE(0,"coef mismatch, column %d row %d", c, r);
+ nerr++;
+ }
+ }
+ }
+ if (f->ucindx[f->uc_space] != 0)
+ {
+ MESSAGE(0,"last ucindx entry %d != 0", f->ucindx[f->uc_space]);
+ nerr++;
+ }
+ if (nerr)
+ {
+ dump_matrix (f, 0);
+ return E_CHECK_FAILED;
+ }
+ return 0;
+}
+#endif
+
+#ifdef FACTOR_STATS
+static void dump_factor_stats (
+ EGLPNUM_TYPENAME_factor_work * f)
+{
+ int dim = f->dim;
+ int ecnt = f->etacnt;
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+ EGLPNUM_TYPENAME_lc_info *lc_inf = f->lc_inf;
+ EGLPNUM_TYPENAME_er_info *er_inf = f->er_inf;
+ EGLPNUM_TYPE *urcoef = f->urcoef;
+ EGLPNUM_TYPE *lccoef = f->lccoef;
+ EGLPNUM_TYPE *ercoef = f->ercoef;
+ int lnzcnt = 0;
+ int unzcnt = 0;
+ int enzcnt = 0;
+ int nzcnt;
+ int beg;
+ EGLPNUM_TYPE umax;
+ EGLPNUM_TYPE lmax;
+ EGLPNUM_TYPE emax;
+ int i;
+ int j;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (umax);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (lmax);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (emax);
+ EGLPNUM_TYPENAME_EGlpNumZero (umax);
+ for (i = 0; i < dim; i++)
+ {
+ nzcnt = ur_inf[i].nzcnt;
+ beg = ur_inf[i].rbeg;
+ unzcnt += nzcnt;
+ for (j = 0; j < nzcnt; j++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (umax, urcoef[beg + j]);
+ }
+ }
+ EGLPNUM_TYPENAME_EGlpNumZero (lmax);
+ for (i = 0; i < dim; i++)
+ {
+ nzcnt = lc_inf[i].nzcnt;
+ beg = lc_inf[i].cbeg;
+ lnzcnt += nzcnt;
+ for (j = 0; j < nzcnt; j++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (lmax, lccoef[beg + j]);
+ }
+ }
+ EGLPNUM_TYPENAME_EGlpNumZero (emax);
+ for (i = 0; i < ecnt; i++)
+ {
+ nzcnt = er_inf[i].nzcnt;
+ beg = er_inf[i].rbeg;
+ enzcnt += nzcnt;
+ for (j = 0; j < nzcnt; j++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (emax, ercoef[beg + j]);
+ }
+ }
+ MESSAGE(0, "factor U %d nzs %.3e max L %d nzs %.3e max E %d nzs %.3e max",
+ unzcnt, EGLPNUM_TYPENAME_EGlpNumToLf (umax), lnzcnt, EGLPNUM_TYPENAME_EGlpNumToLf (lmax), enzcnt,
+ EGLPNUM_TYPENAME_EGlpNumToLf (emax));
+ EGLPNUM_TYPENAME_EGlpNumClearVar (umax);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (lmax);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (emax);
+}
+#endif
+
+static void clear_work (
+ EGLPNUM_TYPENAME_factor_work * f)
+{
+ int i;
+ int dim = f->dim;
+ EGLPNUM_TYPE *work_coef = f->work_coef;
+
+ for (i = 0; i < dim; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumZero (work_coef[i]);
+ }
+}
+
+static void load_row (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int r)
+{
+ EGLPNUM_TYPE *prow_urcoef = f->urcoef + f->ur_inf[r].rbeg;
+ int *prow_urindx = f->urindx + f->ur_inf[r].rbeg;
+ int prow_nzcnt = f->ur_inf[r].nzcnt;
+ EGLPNUM_TYPE *work_coef = f->work_coef;
+ int *work_indx = f->work_indx;
+ int i;
+ int j;
+
+ for (i = 0; i < prow_nzcnt; i++)
+ {
+ j = prow_urindx[i];
+ EGLPNUM_TYPENAME_EGlpNumCopy (work_coef[j], prow_urcoef[i]);
+ work_indx[j] = 1;
+ }
+}
+
+static void clear_row (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int r)
+{
+ int *prow_urindx = f->urindx + f->ur_inf[r].rbeg;
+ int prow_nzcnt = f->ur_inf[r].nzcnt;
+ EGLPNUM_TYPE *work_coef = f->work_coef;
+ int *work_indx = f->work_indx;
+ int i;
+ int j;
+
+ for (i = 0; i < prow_nzcnt; i++)
+ {
+ j = prow_urindx[i];
+ EGLPNUM_TYPENAME_EGlpNumZero (work_coef[j]);
+ work_indx[j] = 0;
+ }
+}
+
+static int make_ur_space (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int space)
+{
+ EGLPNUM_TYPE *new_urcoef = 0;
+ int *new_urindx = 0;
+ int *new_urcind = 0;
+ EGLPNUM_TYPE *urcoef = f->urcoef;
+ int *urindx = f->urindx;
+ int *urcind = f->urcind;
+ int minspace;
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+ int dim = f->dim;
+ int new_nzcnt = 0, old_nzcnt;
+ int rbeg;
+ int nzcnt;
+ int i;
+ int j;
+ int rval;
+
+ minspace = f->ur_space;
+ nzcnt = space;
+ for (i = 0; i < dim; i++)
+ nzcnt += ur_inf[i].nzcnt;
+ old_nzcnt = nzcnt;
+ while (nzcnt * 2 >= minspace)
+ {
+ minspace = 1 + minspace * f->grow_mul;
+ }
+
+#ifdef GROWTH_STATS
+ QSlog("make_ur_space growing from %d to %d...", f->ur_space, minspace);
+#endif
+ new_urcoef = EGLPNUM_TYPENAME_EGlpNumAllocArray (minspace);
+ ILL_SAFE_MALLOC (new_urindx, minspace + 1, int);
+
+ if (urcind)
+ {
+ ILL_SAFE_MALLOC (new_urcind, minspace, int);
+ }
+
+ if (urcind)
+ {
+ for (j = 0; j < dim; j++)
+ {
+ rbeg = ur_inf[j].rbeg;
+ nzcnt = ur_inf[j].nzcnt;
+ ur_inf[j].rbeg = new_nzcnt;
+ for (i = 0; i < nzcnt; i++)
+ {
+ new_urindx[new_nzcnt] = urindx[rbeg + i];
+ EGLPNUM_TYPENAME_EGlpNumCopy (new_urcoef[new_nzcnt], urcoef[rbeg + i]);
+ new_urcind[new_nzcnt] = urcind[rbeg + i];
+ new_nzcnt++;
+ }
+ }
+ }
+ else
+ {
+ for (j = 0; j < dim; j++)
+ {
+ rbeg = ur_inf[j].rbeg;
+ nzcnt = ur_inf[j].nzcnt;
+ ur_inf[j].rbeg = new_nzcnt;
+ for (i = 0; i < nzcnt; i++)
+ {
+ new_urindx[new_nzcnt] = urindx[rbeg + i];
+ EGLPNUM_TYPENAME_EGlpNumCopy (new_urcoef[new_nzcnt], urcoef[rbeg + i]);
+ new_nzcnt++;
+ }
+ }
+ }
+
+ for (i = new_nzcnt; i < minspace; i++)
+ {
+ new_urindx[i] = -1;
+ }
+ new_urindx[minspace] = 0;
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (f->urcoef);
+ f->urcoef = new_urcoef;
+ new_urcoef = 0;
+
+ ILL_IFFREE (f->urindx, int);
+
+ f->urindx = new_urindx;
+ new_urindx = 0;
+
+ ILL_IFFREE (f->urcind, int);
+
+ f->urcind = new_urcind;
+ new_urcind = 0;
+
+ f->ur_freebeg = new_nzcnt;
+ f->ur_space = minspace;
+
+#ifdef GROWTH_STATS
+ MESSAGE (0,"%d/%d nonzeros", new_nzcnt, old_nzcnt);
+ dump_factor_stats (f);
+#endif
+
+ rval = 0;
+
+CLEANUP:
+ ILL_IFFREE (new_urcoef, EGLPNUM_TYPE);
+ ILL_IFFREE (new_urindx, int);
+ ILL_IFFREE (new_urcind, int);
+
+ EG_RETURN (rval);
+}
+
+static int make_uc_space (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int space)
+{
+ EGLPNUM_TYPE *new_uccoef = 0;
+ int *new_ucindx = 0;
+ int *new_ucrind = 0;
+ int uc_freebeg = f->uc_freebeg;
+ EGLPNUM_TYPE *uccoef = f->uccoef;
+ int *ucindx = f->ucindx;
+ int *ucrind = f->ucrind;
+ int minspace = uc_freebeg + space;
+ EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+ int dim = f->dim;
+ int new_nzcnt = 0;
+ int cbeg;
+ int nzcnt;
+ int i;
+ int j;
+ int rval;
+
+ minspace = f->uc_space;
+ nzcnt = space;
+ for( i = 0 ; i < dim ; i++) nzcnt += uc_inf[i].nzcnt;
+ while(nzcnt*2 >= minspace)
+ {
+ minspace = 10 + (f->grow_mul * minspace);
+ }
+
+#ifdef GROWTH_STATS
+ MESSAGE (0,"make_uc_space growing from %d to %d...", f->uc_space, minspace);
+#endif
+
+ ILL_SAFE_MALLOC (new_ucindx, minspace + 1, int);
+
+ if (ucrind)
+ {
+ new_uccoef = EGLPNUM_TYPENAME_EGlpNumAllocArray (minspace);
+ ILL_SAFE_MALLOC (new_ucrind, minspace, int);
+ }
+
+ if (ucrind)
+ {
+ for (j = 0; j < dim; j++)
+ {
+ cbeg = uc_inf[j].cbeg;
+ nzcnt = uc_inf[j].nzcnt;
+ uc_inf[j].cbeg = new_nzcnt;
+ for (i = 0; i < nzcnt; i++)
+ {
+ new_ucindx[new_nzcnt] = ucindx[cbeg + i];
+ EGLPNUM_TYPENAME_EGlpNumCopy (new_uccoef[new_nzcnt], uccoef[cbeg + i]);
+ new_ucrind[new_nzcnt] = ucrind[cbeg + i];
+ new_nzcnt++;
+ }
+ }
+ }
+ else
+ {
+ for (j = 0; j < dim; j++)
+ {
+ cbeg = uc_inf[j].cbeg;
+ nzcnt = uc_inf[j].nzcnt;
+ uc_inf[j].cbeg = new_nzcnt;
+ for (i = 0; i < nzcnt; i++)
+ {
+ new_ucindx[new_nzcnt] = ucindx[cbeg + i];
+ new_nzcnt++;
+ }
+ }
+ }
+
+ for (i = new_nzcnt; i < minspace; i++)
+ {
+ new_ucindx[i] = -1;
+ }
+ new_ucindx[minspace] = 0;
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (f->uccoef);
+ f->uccoef = new_uccoef;
+ new_uccoef = 0;
+
+ ILL_IFFREE (f->ucindx, int);
+
+ f->ucindx = new_ucindx;
+ new_ucindx = 0;
+
+ ILL_IFFREE (f->ucrind, int);
+
+ f->ucrind = new_ucrind;
+ new_ucrind = 0;
+
+ f->uc_freebeg = new_nzcnt;
+ f->uc_space = minspace;
+
+#ifdef GROWTH_STATS
+ MESSAGE (0,"%d nonzeros", new_nzcnt);
+ dump_factor_stats (f);
+#endif
+
+ rval = 0;
+
+CLEANUP:
+ ILL_IFFREE (new_uccoef, EGLPNUM_TYPE);
+ ILL_IFFREE (new_ucindx, int);
+ ILL_IFFREE (new_ucrind, int);
+
+ EG_RETURN (rval);
+}
+
+static int make_lc_space (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int space)
+{
+ EGLPNUM_TYPE *new_lccoef = 0;
+ int *new_lcindx = 0;
+ int lc_freebeg = f->lc_freebeg;
+ EGLPNUM_TYPE *lccoef = f->lccoef;
+ int *lcindx = f->lcindx;
+ int minspace = lc_freebeg + space;
+ int i;
+ int rval;
+
+ if (f->lc_space * f->grow_mul > minspace)
+ {
+ minspace = f->lc_space * f->grow_mul;
+ }
+
+#ifdef GROWTH_STATS
+ MESSAGE (0,"make_lc_space growing from %d to %d...", f->lc_space, minspace);
+#endif
+
+ new_lccoef = EGLPNUM_TYPENAME_EGlpNumAllocArray (minspace);
+ ILL_SAFE_MALLOC (new_lcindx, minspace, int);
+
+ for (i = 0; i < lc_freebeg; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (new_lccoef[i], lccoef[i]);
+ new_lcindx[i] = lcindx[i];
+ }
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (lccoef);
+ f->lccoef = new_lccoef;
+ new_lccoef = 0;
+
+ ILL_IFFREE (lcindx, int);
+
+ f->lcindx = new_lcindx;
+ new_lcindx = 0;
+
+ f->lc_space = minspace;
+
+#ifdef GROWTH_STATS
+ dump_factor_stats (f);
+#endif
+
+ rval = 0;
+
+CLEANUP:
+ ILL_IFFREE (new_lccoef, EGLPNUM_TYPE);
+ ILL_IFFREE (new_lcindx, int);
+
+ EG_RETURN (rval);
+}
+
+static void set_col_nz (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int c)
+{
+ EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+ int nzcnt = uc_inf[c].nzcnt;
+ int max_k = f->max_k;
+ int dim = f->dim;
+
+ if (uc_inf[c].next >= 0)
+ {
+ uc_inf[uc_inf[c].next].prev = uc_inf[c].prev;
+ uc_inf[uc_inf[c].prev].next = uc_inf[c].next;
+
+ if (nzcnt >= max_k)
+ nzcnt = max_k;
+ uc_inf[c].next = uc_inf[dim + nzcnt].next;
+ uc_inf[c].prev = dim + nzcnt;
+ uc_inf[dim + nzcnt].next = c;
+ uc_inf[uc_inf[c].next].prev = c;
+ }
+}
+
+static void set_row_nz (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int r)
+{
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+ int nzcnt = ur_inf[r].pivcnt;
+ int max_k = f->max_k;
+ int dim = f->dim;
+
+ if (ur_inf[r].next >= 0)
+ {
+ ur_inf[ur_inf[r].next].prev = ur_inf[r].prev;
+ ur_inf[ur_inf[r].prev].next = ur_inf[r].next;
+
+ if (nzcnt >= max_k)
+ nzcnt = max_k;
+ ur_inf[r].next = ur_inf[dim + nzcnt].next;
+ ur_inf[r].prev = dim + nzcnt;
+ ur_inf[dim + nzcnt].next = r;
+ ur_inf[ur_inf[r].next].prev = r;
+ }
+}
+
+static void remove_col_nz (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int r,
+ int c)
+{
+ EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+ int *ucindx = f->ucindx + uc_inf[c].cbeg;
+ int nzcnt = uc_inf[c].nzcnt;
+ int i;
+
+ for (i = 0; i < nzcnt; i++)
+ {
+ if (ucindx[i] == r)
+ {
+ --nzcnt;
+ ucindx[i] = ucindx[nzcnt];
+ ucindx[nzcnt] = -1;
+ break;
+ }
+ }
+ uc_inf[c].nzcnt = nzcnt;
+
+ set_col_nz (f, c);
+}
+
+static void remove_row_nz (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int r,
+ int c)
+{
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+ int *urindx = f->urindx + ur_inf[r].rbeg;
+ EGLPNUM_TYPE *urcoef = f->urcoef + ur_inf[r].rbeg;
+ int pivcnt = ur_inf[r].pivcnt;
+ EGLPNUM_TYPE max;
+ int tind;
+ EGLPNUM_TYPE tcoef;
+ int i;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (tcoef);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (max);
+ EGLPNUM_TYPENAME_EGlpNumZero (max);
+
+ for (i = 0; i < pivcnt; i++)
+ {
+ if (urindx[i] == c)
+ {
+ --pivcnt;
+ ILL_SWAP (urindx[i], urindx[pivcnt], tind);
+ EGLPNUM_TYPENAME_EGLPNUM_SWAP (urcoef[i], urcoef[pivcnt], tcoef);
+ --i;
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (max, urcoef[i]);
+ }
+ }
+ ur_inf[r].pivcnt = pivcnt;
+ EGLPNUM_TYPENAME_EGlpNumCopy (ur_inf[r].max, max);
+ set_row_nz (f, r);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (max);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (tcoef);
+}
+
+static int add_col_nz (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int r,
+ int c)
+{
+ EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+ int cbeg = uc_inf[c].cbeg;
+ int nzcnt = uc_inf[c].nzcnt;
+ int uc_freebeg = f->uc_freebeg;
+ int *ucindx = f->ucindx;
+ int i;
+ int rval = 0;
+
+ if (uc_inf[c].next == -1)
+ {
+ return 0;
+ }
+
+ if (ucindx[cbeg + nzcnt] == -1)
+ {
+ ucindx[cbeg + nzcnt] = r;
+ uc_inf[c].nzcnt++;
+ if (nzcnt + cbeg == uc_freebeg)
+ {
+ f->uc_freebeg = uc_freebeg + 1;
+ }
+ }
+ else
+ {
+ if (uc_freebeg + nzcnt + 1 >= f->uc_space)
+ {
+ rval = make_uc_space (f, nzcnt + 1);
+ CHECKRVALG (rval, CLEANUP);
+ uc_freebeg = f->uc_freebeg;
+ cbeg = uc_inf[c].cbeg;
+ ucindx = f->ucindx;
+ }
+ for (i = 0; i < nzcnt; i++)
+ {
+ ucindx[uc_freebeg + i] = ucindx[cbeg + i];
+ ucindx[cbeg + i] = -1;
+ }
+ ucindx[uc_freebeg + nzcnt] = r;
+ uc_inf[c].cbeg = uc_freebeg;
+ uc_inf[c].nzcnt++;
+ f->uc_freebeg = uc_freebeg + nzcnt + 1;
+ }
+
+ set_col_nz (f, c);
+CLEANUP:
+ EG_RETURN (rval);
+}
+
+static void disable_col (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int c)
+{
+ EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+
+ if (uc_inf[c].next >= 0)
+ {
+ uc_inf[uc_inf[c].next].prev = uc_inf[c].prev;
+ uc_inf[uc_inf[c].prev].next = uc_inf[c].next;
+
+ uc_inf[c].next = -2;
+ uc_inf[c].prev = -2;
+ }
+}
+
+static void remove_col (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int c)
+{
+ EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+ int cbeg = uc_inf[c].cbeg;
+ int nzcnt = uc_inf[c].nzcnt;
+ int *ucindx = f->ucindx;
+ int i;
+
+ for (i = 0; i < nzcnt; i++)
+ {
+ ucindx[cbeg + i] = -1;
+ }
+ uc_inf[c].cbeg = 0;
+ uc_inf[c].nzcnt = 0;
+
+ if (uc_inf[c].next >= 0)
+ {
+ uc_inf[uc_inf[c].next].prev = uc_inf[c].prev;
+ uc_inf[uc_inf[c].prev].next = uc_inf[c].next;
+
+ uc_inf[c].next = -1;
+ uc_inf[c].prev = -1;
+ }
+}
+
+static void remove_row (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int r)
+{
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+
+ if (ur_inf[r].next >= 0)
+ {
+ ur_inf[ur_inf[r].next].prev = ur_inf[r].prev;
+ ur_inf[ur_inf[r].prev].next = ur_inf[r].next;
+
+ ur_inf[r].next = -1;
+ ur_inf[r].prev = -1;
+ }
+}
+
+static void find_coef (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int r,
+ int c,
+ EGLPNUM_TYPE * coef)
+{
+ EGLPNUM_TYPE *prow_urcoef = f->urcoef + f->ur_inf[r].rbeg;
+ int *prow_urindx = f->urindx + f->ur_inf[r].rbeg;
+ int i;
+ int prow_nzcnt = f->ur_inf[r].nzcnt;
+
+ EGLPNUM_TYPENAME_EGlpNumZero (*coef);
+ for (i = 0; i < prow_nzcnt; i++)
+ {
+ if (prow_urindx[i] == c)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (*coef, prow_urcoef[i]);
+ return;
+ }
+ }
+ QSlog("Coefficient not found");
+ return;
+}
+
+static int elim_row (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int elim_r,
+ int r,
+ int c,
+ EGLPNUM_TYPE * p_pivot_coef)
+{
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+ EGLPNUM_TYPE *work_coef = f->work_coef;
+ int *work_indx = f->work_indx;
+ EGLPNUM_TYPE *urcoef = f->urcoef;
+ int *urindx = f->urindx;
+ int prow_beg = ur_inf[r].rbeg;
+ int prow_nzcnt = ur_inf[r].nzcnt;
+ int prow_pivcnt = ur_inf[r].pivcnt;
+ int fill = ur_inf[elim_r].nzcnt;
+ int cancel = 0;
+ EGLPNUM_TYPE max;
+ int erow_beg;
+ int erow_nzcnt;
+ int erow_pivcnt;
+ EGLPNUM_TYPE x;
+ int i;
+ int j;
+ int rval = 0;
+ EGLPNUM_TYPE elim_coef;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (max);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (x);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (elim_coef);
+ EGLPNUM_TYPENAME_EGlpNumZero (max);
+ find_coef (f, r, c, &elim_coef);
+ EGLPNUM_TYPENAME_EGlpNumDivTo (elim_coef, work_coef[c]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (*p_pivot_coef, elim_coef);
+
+ for (i = 0; i < prow_nzcnt; i++)
+ {
+ j = urindx[prow_beg + i];
+ if (work_indx[j] == 1)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (x, urcoef[prow_beg + i]);
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (x, elim_coef, work_coef[j]);
+ if ((!(EGLPNUM_TYPENAME_EGlpNumIsNeqZero (x, f->fzero_tol))) || j == c)
+ {
+ cancel++;
+ if (j != c)
+ {
+ remove_col_nz (f, r, j);
+ }
+ if (i < prow_pivcnt)
+ {
+ prow_pivcnt--;
+ prow_nzcnt--;
+ urindx[prow_beg + i] = urindx[prow_beg + prow_pivcnt];
+ EGLPNUM_TYPENAME_EGlpNumCopy (urcoef[prow_beg + i], urcoef[prow_beg + prow_pivcnt]);
+ if (prow_pivcnt != prow_nzcnt)
+ {
+ urindx[prow_beg + prow_pivcnt] = urindx[prow_beg + prow_nzcnt];
+ EGLPNUM_TYPENAME_EGlpNumCopy (urcoef[prow_beg + prow_pivcnt],
+ urcoef[prow_beg + prow_nzcnt]);
+ }
+ }
+ else
+ {
+ prow_nzcnt--;
+ urindx[prow_beg + i] = urindx[prow_beg + prow_nzcnt];
+ EGLPNUM_TYPENAME_EGlpNumCopy (urcoef[prow_beg + i], urcoef[prow_beg + prow_nzcnt]);
+ }
+ urindx[prow_beg + prow_nzcnt] = -1;
+ i--;
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (urcoef[prow_beg + i], x);
+ if (i < prow_pivcnt)
+ {
+ EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (max, x);
+ }
+ }
+ work_indx[j] = 0;
+ fill--;
+ }
+ else
+ {
+ if (i < prow_pivcnt)
+ {
+ EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (max, urcoef[prow_beg + i]);
+ }
+ }
+ }
+
+ if (fill > 0)
+ {
+ ur_inf[r].nzcnt = prow_nzcnt;
+ ur_inf[r].pivcnt = prow_pivcnt;
+ if (fill > cancel)
+ {
+ int ur_freebeg = f->ur_freebeg;
+
+ if (ur_freebeg + prow_nzcnt + fill >= f->ur_space)
+ {
+ rval = make_ur_space (f, prow_nzcnt + fill);
+ CHECKRVALG (rval, CLEANUP);
+ urcoef = f->urcoef;
+ urindx = f->urindx;
+ ur_freebeg = f->ur_freebeg;
+ prow_beg = f->ur_inf[r].rbeg;
+ }
+ for (i = 0; i < prow_nzcnt; i++)
+ {
+ urindx[ur_freebeg + i] = urindx[prow_beg + i];
+ EGLPNUM_TYPENAME_EGlpNumCopy (urcoef[ur_freebeg + i], urcoef[prow_beg + i]);
+ urindx[prow_beg + i] = -1;
+ }
+ ur_inf[r].rbeg = ur_freebeg;
+ f->ur_freebeg = ur_freebeg + prow_nzcnt + fill;
+ prow_beg = ur_freebeg;
+ }
+
+ erow_beg = ur_inf[elim_r].rbeg;
+ erow_nzcnt = ur_inf[elim_r].nzcnt;
+ erow_pivcnt = ur_inf[elim_r].pivcnt;
+
+ for (i = 0; i < erow_pivcnt; i++)
+ {
+ j = urindx[erow_beg + i];
+ if (work_indx[j] == 1)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyNeg (x, elim_coef);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (x, urcoef[erow_beg + i]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (x, f->fzero_tol))
+ {
+ rval = add_col_nz (f, r, j);
+ CHECKRVALG (rval, CLEANUP);
+ if (prow_pivcnt != prow_nzcnt)
+ {
+ urindx[prow_beg + prow_nzcnt] = urindx[prow_beg + prow_pivcnt];
+ EGLPNUM_TYPENAME_EGlpNumCopy (urcoef[prow_beg + prow_nzcnt],
+ urcoef[prow_beg + prow_pivcnt]);
+ }
+ urindx[prow_beg + prow_pivcnt] = j;
+ EGLPNUM_TYPENAME_EGlpNumCopy (urcoef[prow_beg + prow_pivcnt], x);
+ EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (max, x);
+ prow_pivcnt++;
+ prow_nzcnt++;
+ }
+ }
+ else
+ {
+ work_indx[j] = 1;
+ }
+ }
+ for (i = erow_pivcnt; i < erow_nzcnt; i++)
+ {
+ j = urindx[erow_beg + i];
+ if (work_indx[j] == 1)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyNeg (x, elim_coef);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (x, urcoef[erow_beg + i]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (x, f->fzero_tol))
+ {
+ rval = add_col_nz (f, r, j);
+ CHECKRVALG (rval, CLEANUP);
+ urindx[prow_beg + prow_nzcnt] = j;
+ EGLPNUM_TYPENAME_EGlpNumCopy (urcoef[prow_beg + prow_nzcnt], x);
+ prow_nzcnt++;
+ }
+ }
+ else
+ {
+ work_indx[j] = 1;
+ }
+ }
+ }
+ else
+ {
+ erow_nzcnt = ur_inf[elim_r].nzcnt;
+ erow_beg = ur_inf[elim_r].rbeg;
+ for (i = 0; i < erow_nzcnt; i++)
+ {
+ j = urindx[erow_beg + i];
+ work_indx[j] = 1;
+ }
+ }
+
+ ur_inf[r].nzcnt = prow_nzcnt;
+ ur_inf[r].pivcnt = prow_pivcnt;
+ EGLPNUM_TYPENAME_EGlpNumCopy (ur_inf[r].max, max);
+
+ set_row_nz (f, r);
+CLEANUP:
+ EGLPNUM_TYPENAME_EGlpNumClearVar (elim_coef);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (x);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (max);
+ EG_RETURN (rval);
+}
+
+#define SETPERM(f,s,r,c) { \
+ f->rperm[f->rrank[r]] = f->rperm[s]; \
+ f->rrank[f->rperm[s]] = f->rrank[r]; \
+ f->rperm[s] = r; \
+ f->rrank[r] = s; \
+ \
+ f->cperm[f->crank[c]] = f->cperm[s]; \
+ f->crank[f->cperm[s]] = f->crank[c]; \
+ f->cperm[s] = c; \
+ f->crank[c] = s; \
+}
+
+static int elim (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int r,
+ int c)
+{
+ EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+ EGLPNUM_TYPENAME_lc_info *lc_inf = f->lc_inf;
+ int *urindx;
+ int *ucindx;
+ int *lcindx;
+ EGLPNUM_TYPE *urcoef;
+ EGLPNUM_TYPE *lccoef;
+ EGLPNUM_TYPE pivot_coef;
+ int nzcnt;
+ int lc_freebeg;
+ int s = f->stage;
+ int i;
+ int j;
+ int rval = 0;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (pivot_coef);
+
+ if (uc_inf[c].nzcnt == 1)
+ {
+ /* col singleton */
+ SETPERM (f, s, r, c);
+
+ lc_inf[s].cbeg = -1;
+ lc_inf[s].c = r;
+ lc_inf[s].nzcnt = 0;
+ f->stage++;
+
+ urindx = f->urindx + ur_inf[r].rbeg;
+ urcoef = f->urcoef + ur_inf[r].rbeg;
+ nzcnt = ur_inf[r].nzcnt;
+ for (i = 0; i < nzcnt; i++)
+ {
+ j = urindx[i];
+ remove_col_nz (f, r, j);
+ if (j == c)
+ {
+ urindx[i] = urindx[0];
+ urindx[0] = c;
+ EGLPNUM_TYPENAME_EGLPNUM_SWAP (urcoef[0], urcoef[i], pivot_coef);
+ }
+ }
+ remove_row (f, r);
+ remove_col (f, c);
+ }
+ else if (ur_inf[r].nzcnt == 1)
+ {
+ /* row singleton */
+ --(f->nstages);
+ SETPERM (f, f->nstages, r, c);
+
+ lc_inf[f->nstages].cbeg = -1;
+ lc_inf[f->nstages].c = r;
+ lc_inf[f->nstages].nzcnt = 0;
+
+ ucindx = f->ucindx + uc_inf[c].cbeg;
+ nzcnt = uc_inf[c].nzcnt;
+ for (i = 0; i < nzcnt; i++)
+ {
+ j = ucindx[i];
+ remove_row_nz (f, j, c);
+ }
+ remove_row (f, r);
+ remove_col (f, c);
+ }
+ else
+ {
+ SETPERM (f, s, r, c);
+ f->stage++;
+
+ nzcnt = uc_inf[c].nzcnt;
+ if (f->lc_freebeg + nzcnt >= f->lc_space)
+ {
+ rval = make_lc_space (f, nzcnt);
+ CHECKRVALG (rval, CLEANUP);
+ }
+ lc_freebeg = f->lc_freebeg;
+ lc_inf[s].cbeg = lc_freebeg;
+ lc_inf[s].c = r;
+ lcindx = f->lcindx;
+ lccoef = f->lccoef;
+ load_row (f, r);
+ ucindx = f->ucindx + uc_inf[c].cbeg;
+ for (i = 0; i < nzcnt; i++)
+ {
+ j = f->ucindx[uc_inf[c].cbeg + i];
+ if (j != r)
+ {
+ rval = elim_row (f, r, j, c, &pivot_coef);
+ CHECKRVALG (rval, CLEANUP);
+ lcindx[lc_freebeg] = j;
+ EGLPNUM_TYPENAME_EGlpNumCopy (lccoef[lc_freebeg], pivot_coef);
+ lc_freebeg++;
+#ifdef TRACK_FACTOR
+ EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (f->maxelem_factor, pivot_coef);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (f->maxelem_factor, ur_inf[r].max))
+ EGLPNUM_TYPENAME_EGlpNumCopy (f->maxelem_factor, ur_inf[r].max);
+#endif /* TRACK_FACTOR */
+ }
+ }
+ lc_inf[s].nzcnt = lc_freebeg - lc_inf[s].cbeg;
+ f->lc_freebeg = lc_freebeg;
+
+ clear_row (f, r);
+
+ urindx = f->urindx + ur_inf[r].rbeg;
+ urcoef = f->urcoef + ur_inf[r].rbeg;
+ nzcnt = ur_inf[r].nzcnt;
+ for (i = 0; i < nzcnt; i++)
+ {
+ j = urindx[i];
+ remove_col_nz (f, r, j);
+ if (j == c)
+ {
+ urindx[i] = urindx[0];
+ urindx[0] = c;
+ EGLPNUM_TYPENAME_EGLPNUM_SWAP (urcoef[0], urcoef[i], pivot_coef);
+ }
+ }
+ remove_row (f, r);
+ remove_col (f, c);
+ }
+CLEANUP:
+ EGLPNUM_TYPENAME_EGlpNumClearVar (pivot_coef);
+ EG_RETURN (rval);
+}
+
+static void find_pivot_column (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int c,
+ int *p_r)
+{
+ EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+ int *ucindx = f->ucindx;
+ int nzcnt = uc_inf[c].nzcnt;
+ int cbeg = uc_inf[c].cbeg;
+ EGLPNUM_TYPE num_tmp[2];
+ int bestnz = -1;
+ int i;
+ int r;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (num_tmp[0]);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (num_tmp[1]);
+
+ *p_r = -1;
+ for (i = 0; i < nzcnt; i++)
+ {
+ r = ucindx[cbeg + i];
+ if((bestnz == -1 || ur_inf[r].pivcnt < bestnz))
+ {
+ find_coef (f, r, c, num_tmp);
+ if(EGLPNUM_TYPENAME_EGlpNumIsLessZero(num_tmp[0]))
+ EGLPNUM_TYPENAME_EGlpNumSign (num_tmp[0]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (num_tmp[1], f->partial_cur);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (num_tmp[1], ur_inf[r].max);
+ if(EGLPNUM_TYPENAME_EGlpNumIsLeq (num_tmp[1], num_tmp[0]))
+ {
+ bestnz = ur_inf[r].pivcnt;
+ *p_r = r;
+ }
+ }
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (num_tmp[0]);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (num_tmp[1]);
+}
+
+static void find_pivot_row (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int r,
+ int *p_c)
+{
+ EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+ int *urindx = f->urindx;
+ EGLPNUM_TYPE *urcoef = f->urcoef;
+ int pivcnt = ur_inf[r].pivcnt;
+ int rbeg = ur_inf[r].rbeg;
+ EGLPNUM_TYPE thresh[2];
+ int bestnz = -1;
+ int i;
+ int c;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (thresh[0]);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (thresh[1]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (thresh[0], f->partial_cur);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (thresh[0], ur_inf[r].max);
+ *p_c = -1;
+ for (i = 0; i < pivcnt; i++)
+ {
+ c = urindx[rbeg + i];
+ if ((bestnz == -1 || uc_inf[c].nzcnt < bestnz))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs (thresh[1], urcoef[rbeg + i]);
+ if(EGLPNUM_TYPENAME_EGlpNumIsLeq (thresh[0], thresh[1]))
+ {
+ bestnz = uc_inf[c].nzcnt;
+ *p_c = c;
+ }
+ }
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (thresh[0]);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (thresh[1]);
+}
+
+static int find_pivot (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int *p_r,
+ int *p_c)
+{
+ EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+ int dim = f->dim;
+ int max_k = f->max_k;
+ int p = f->p;
+ int c;
+ int r;
+ int mm = 0;
+ int n = 0;
+ int m;
+ int k = 2;
+
+ if (uc_inf[dim + 1].next != dim + 1)
+ {
+ c = uc_inf[dim + 1].next;
+ r = f->ucindx[uc_inf[c].cbeg];
+ *p_c = c;
+ *p_r = r;
+ return 0;
+ }
+ else if (ur_inf[dim + 1].next != dim + 1)
+ {
+ r = ur_inf[dim + 1].next;
+ c = f->urindx[ur_inf[r].rbeg];
+ *p_c = c;
+ *p_r = r;
+ return 0;
+ }
+ *p_r = -1;
+ *p_c = -1;
+ for (; k <= max_k && (mm == 0 || mm > (k - 1) * (k - 1)); k++)
+ {
+ if (uc_inf[dim + k].next != dim + k)
+ {
+ for (c = uc_inf[dim + k].next; c != dim + k; c = uc_inf[c].next)
+ {
+ find_pivot_column (f, c, &r);
+ if (r >= 0)
+ {
+ m = (uc_inf[c].nzcnt - 1) * (ur_inf[r].pivcnt - 1);
+ if (mm == 0 || m < mm)
+ {
+ mm = m;
+ *p_c = c;
+ *p_r = r;
+ if (mm <= (k - 1) * (k - 1))
+ {
+ return 0;
+ }
+ }
+ }
+ else
+ {
+ c = uc_inf[c].prev;
+ disable_col (f, uc_inf[c].next);
+ }
+ n++;
+ if (n >= p && mm != 0)
+ {
+ return 0;
+ }
+ }
+ }
+
+ if (ur_inf[dim + k].next != dim + k)
+ {
+ for (r = ur_inf[dim + k].next; r != dim + k; r = ur_inf[r].next)
+ {
+ find_pivot_row (f, r, &c);
+ if (c >= 0)
+ {
+ m = (uc_inf[c].nzcnt - 1) * (ur_inf[r].pivcnt - 1);
+ if (mm == 0 || m < mm)
+ {
+ mm = m;
+ *p_c = c;
+ *p_r = r;
+ if (mm <= k * (k - 1))
+ {
+ return 0;
+ }
+ }
+ }
+ n++;
+ if (n >= p && mm != 0)
+ {
+ return 0;
+ }
+ }
+ }
+ }
+ if (mm != 0)
+ {
+ return 0;
+ }
+ else
+ {
+ //QSlog("No acceptable pivot found");
+ return E_NO_PIVOT;
+ }
+}
+
+static int create_factor_space (
+ EGLPNUM_TYPENAME_factor_work * f)
+{
+ EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+ int dim = f->dim;
+ int nzcnt;
+ int i;
+ int rval;
+
+ nzcnt = 0;
+ for (i = 0; i < dim; i++)
+ {
+ nzcnt += ur_inf[i].nzcnt;
+ }
+
+ if (f->ucindx == 0)
+ {
+ f->uc_space = nzcnt * f->uc_space_mul;
+ ILL_SAFE_MALLOC (f->ucindx, f->uc_space + 1, int);
+ }
+
+ if (f->urindx == 0 || f->urcoef == 0)
+ {
+ ILL_IFFREE (f->urindx, int);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (f->urcoef);
+ f->ur_space = nzcnt * f->ur_space_mul;
+ ILL_SAFE_MALLOC (f->urindx, f->ur_space + 1, int);
+
+ f->urcoef = EGLPNUM_TYPENAME_EGlpNumAllocArray (f->ur_space);
+ }
+
+ if (f->lcindx == 0 || f->lccoef == 0)
+ {
+ ILL_IFFREE (f->lcindx, int);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (f->lccoef);
+ f->lc_space = nzcnt * f->lc_space_mul;
+ ILL_SAFE_MALLOC (f->lcindx, f->lc_space, int);
+
+ f->lccoef = EGLPNUM_TYPENAME_EGlpNumAllocArray (f->lc_space);
+ }
+
+ nzcnt = 0;
+ for (i = 0; i < dim; i++)
+ {
+ ur_inf[i].rbeg = nzcnt;
+ nzcnt += ur_inf[i].nzcnt;
+ ur_inf[i].nzcnt = ur_inf[i].rbeg;
+ }
+ f->ur_freebeg = nzcnt;
+
+ nzcnt = 0;
+ for (i = 0; i < dim; i++)
+ {
+ uc_inf[i].cbeg = nzcnt;
+ nzcnt += uc_inf[i].nzcnt;
+ uc_inf[i].nzcnt = uc_inf[i].cbeg;
+ }
+ f->uc_freebeg = nzcnt;
+
+ f->lc_freebeg = 0;
+
+ rval = 0;
+CLEANUP:
+ EG_RETURN (rval);
+}
+
+static int init_matrix (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int *basis,
+ int *cbeg,
+ int *clen,
+ int *in_ucindx,
+ EGLPNUM_TYPE * in_uccoef)
+{
+ EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+ int dim = f->dim;
+ int max_k = f->max_k;
+ int *ucindx;
+ int *urindx;
+ EGLPNUM_TYPE *urcoef;
+ int nzcnt;
+ int beg;
+ int i;
+ int j;
+ int r;
+ int rval = 0;
+ EGLPNUM_TYPE v;
+ EGLPNUM_TYPE max;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (max);
+
+ for (i = 0; i < dim; i++)
+ {
+ ur_inf[i].nzcnt = 0;
+ }
+ for (i = 0; i < dim; i++)
+ {
+ nzcnt = clen[basis[i]];
+ beg = cbeg[basis[i]];
+ uc_inf[i].nzcnt = nzcnt;
+ for (j = 0; j < nzcnt; j++)
+ {
+ r = in_ucindx[beg + j];
+ ur_inf[r].nzcnt++;
+ }
+ }
+
+ rval = create_factor_space (f);
+ CHECKRVALG (rval, CLEANUP);
+
+ urindx = f->urindx;
+ ucindx = f->ucindx;
+ urcoef = f->urcoef;
+
+ for (i = 0; i < dim; i++)
+ {
+ nzcnt = clen[basis[i]];
+ beg = cbeg[basis[i]];
+ for (j = 0; j < nzcnt; j++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (v, in_uccoef[beg + j]);
+ if (!(EGLPNUM_TYPENAME_EGlpNumIsNeqZero (v, f->fzero_tol)))
+ continue;
+ r = in_ucindx[beg + j];
+ ucindx[uc_inf[i].nzcnt++] = r;
+ urindx[ur_inf[r].nzcnt] = i;
+ EGLPNUM_TYPENAME_EGlpNumCopy (urcoef[ur_inf[r].nzcnt], v);
+ ur_inf[r].nzcnt++;
+ }
+ }
+
+ for (i = 0; i < dim; i++)
+ {
+ uc_inf[i].nzcnt -= uc_inf[i].cbeg;
+ ur_inf[i].nzcnt -= ur_inf[i].rbeg;
+ }
+
+ j = f->uc_space;
+ for (i = f->uc_freebeg; i < j; i++)
+ {
+ ucindx[i] = -1;
+ }
+ ucindx[j] = 0;
+
+ j = f->ur_space;
+ for (i = f->ur_freebeg; i < j; i++)
+ {
+ urindx[i] = -1;
+ }
+ urindx[j] = 0;
+
+ for (i = 0; i < dim; i++)
+ {
+ nzcnt = ur_inf[i].nzcnt;
+ ur_inf[i].pivcnt = nzcnt;
+ beg = ur_inf[i].rbeg;
+ EGLPNUM_TYPENAME_EGlpNumZero (max);
+ for (j = 0; j < nzcnt; j++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (max, urcoef[beg + j]);
+ }
+ EGLPNUM_TYPENAME_EGlpNumCopy (ur_inf[i].max, max);
+ }
+
+ for (i = 0; i <= max_k; i++)
+ {
+ ur_inf[dim + i].next = dim + i;
+ ur_inf[dim + i].prev = dim + i;
+ uc_inf[dim + i].next = dim + i;
+ uc_inf[dim + i].prev = dim + i;
+ }
+
+ for (i = 0; i < dim; i++)
+ {
+ nzcnt = uc_inf[i].nzcnt;
+ if (nzcnt >= max_k)
+ nzcnt = max_k;
+ uc_inf[i].next = uc_inf[dim + nzcnt].next;
+ uc_inf[i].prev = dim + nzcnt;
+ uc_inf[dim + nzcnt].next = i;
+ uc_inf[uc_inf[i].next].prev = i;
+
+ nzcnt = ur_inf[i].pivcnt;
+ if (nzcnt >= max_k)
+ nzcnt = max_k;
+ ur_inf[i].next = ur_inf[dim + nzcnt].next;
+ ur_inf[i].prev = dim + nzcnt;
+ ur_inf[dim + nzcnt].next = i;
+ ur_inf[ur_inf[i].next].prev = i;
+ }
+
+#ifdef TRACK_FACTOR
+ EGLPNUM_TYPENAME_EGlpNumZero (max);
+ nzcnt = 0;
+ for (i = 0; i < dim; i++)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (max, ur_inf[i].max))
+ EGLPNUM_TYPENAME_EGlpNumCopy (max, ur_inf[i].max);
+ nzcnt += ur_inf[i].nzcnt;
+ }
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (f->maxelem_orig, max);
+ f->nzcnt_orig = nzcnt;
+ EGLPNUM_TYPENAME_EGlpNumCopy (f->maxelem_factor, f->maxelem_orig);
+ f->nzcnt_factor = f->nzcnt_orig;
+#endif /* TRACK_FACTOR */
+
+ /* sentinal for column space */
+ ucindx[f->uc_space] = 0;
+
+ clear_work (f);
+
+CLEANUP:
+ EGLPNUM_TYPENAME_EGlpNumClearVar (max);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+ EG_RETURN (rval);
+}
+
+static int build_iteration_u_data (
+ EGLPNUM_TYPENAME_factor_work * f)
+{
+ int dim = f->dim;
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+ EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+ EGLPNUM_TYPE *uccoef = 0;
+ int *ucindx = 0;
+ int *urindx = f->urindx;
+ EGLPNUM_TYPE *urcoef = f->urcoef;
+ int *ucrind = 0;
+ int *urcind = 0;
+ int nzcnt;
+ int beg;
+ int cbeg;
+ int cnzcnt;
+ int uc_space = f->uc_space;
+ int er_space;
+ int i;
+ int j;
+ int k;
+ int rval;
+
+ nzcnt = 0;
+ for (i = 0; i < dim; i++)
+ {
+ nzcnt += ur_inf[i].nzcnt;
+ }
+
+#ifdef TRACK_FACTOR
+ f->nzcnt_factor = nzcnt;
+#endif /* TRACK_FACTOR */
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (f->uccoef);
+ uccoef = EGLPNUM_TYPENAME_EGlpNumAllocArray (nzcnt);
+ f->uccoef = uccoef;
+
+ ILL_IFFREE (f->ucrind, int);
+ ILL_SAFE_MALLOC (ucrind, nzcnt, int);
+
+ f->ucrind = ucrind;
+
+ ILL_IFFREE (f->urcind, int);
+ ILL_SAFE_MALLOC (urcind, f->ur_space, int);
+
+ f->urcind = urcind;
+
+ if (uc_space < nzcnt)
+ {
+ ILL_IFFREE (f->ucindx, int);
+ ILL_SAFE_MALLOC (f->ucindx, nzcnt + 1, int);
+ }
+ f->uc_space = nzcnt;
+ uc_space = nzcnt;
+ ucindx = f->ucindx;
+
+ for (i = 0; i < dim; i++)
+ {
+ uc_inf[i].nzcnt = 0;
+ }
+
+ for (i = 0; i < dim; i++)
+ {
+ nzcnt = ur_inf[i].nzcnt;
+ beg = ur_inf[i].rbeg;
+ for (j = 0; j < nzcnt; j++)
+ {
+ uc_inf[urindx[beg + j]].nzcnt++;
+ }
+ ur_inf[i].delay = 0;
+ }
+
+ nzcnt = 0;
+ for (i = 0; i < dim; i++)
+ {
+ uc_inf[i].cbeg = nzcnt;
+ nzcnt += uc_inf[i].nzcnt;
+ uc_inf[i].nzcnt = 0;
+ uc_inf[i].delay = 0;
+ }
+
+ f->uc_freebeg = nzcnt;
+ for (i = nzcnt; i < uc_space; i++)
+ {
+ ucindx[i] = -1;
+ }
+ ucindx[uc_space] = 0;
+
+ for (i = 0; i < dim; i++)
+ {
+ nzcnt = ur_inf[i].nzcnt;
+ beg = ur_inf[i].rbeg;
+ k = urindx[beg];
+ cbeg = uc_inf[k].cbeg;
+ cnzcnt = uc_inf[k].nzcnt;
+ if (cnzcnt != 0)
+ {
+ ucindx[cbeg + cnzcnt] = ucindx[cbeg];
+ EGLPNUM_TYPENAME_EGlpNumCopy (uccoef[cbeg + cnzcnt], uccoef[cbeg]);
+ ucrind[cbeg + cnzcnt] = ucrind[cbeg];
+ urcind[ur_inf[ucindx[cbeg]].rbeg + ucrind[cbeg]] = cnzcnt;
+ }
+ ucindx[cbeg] = i;
+ EGLPNUM_TYPENAME_EGlpNumCopy (uccoef[cbeg], urcoef[beg]);
+ ucrind[cbeg] = 0;
+ urcind[beg] = 0;
+ uc_inf[k].nzcnt = cnzcnt + 1;
+ for (j = 1; j < nzcnt; j++)
+ {
+ k = urindx[beg + j];
+ cbeg = uc_inf[k].cbeg;
+ cnzcnt = uc_inf[k].nzcnt;
+ ucindx[cbeg + cnzcnt] = i;
+ EGLPNUM_TYPENAME_EGlpNumCopy (uccoef[cbeg + cnzcnt], urcoef[beg + j]);
+ ucrind[cbeg + cnzcnt] = j;
+ urcind[beg + j] = cnzcnt;
+ uc_inf[k].nzcnt++;
+ }
+ }
+
+ for (i = 0; i < dim; i++)
+ {
+ f->rrank[f->rperm[i]] = i;
+ }
+
+ nzcnt = f->ur_space;
+
+ for (i = f->ur_freebeg; i < nzcnt; i++)
+ {
+ urindx[i] = -1;
+ }
+ urindx[nzcnt] = 0;
+
+ clear_work (f);
+
+ er_space = f->er_space_mul * f->etamax;
+ ILL_SAFE_MALLOC (f->er_inf, f->etamax, EGLPNUM_TYPENAME_er_info);
+ ILL_SAFE_MALLOC (f->erindx, er_space, int);
+
+ f->ercoef = EGLPNUM_TYPENAME_EGlpNumAllocArray (er_space);
+ f->etacnt = 0;
+ f->er_freebeg = 0;
+ f->er_space = er_space;
+
+ rval = 0;
+
+CLEANUP:
+ EG_RETURN (rval);
+}
+
+static int build_iteration_l_data (
+ EGLPNUM_TYPENAME_factor_work * f)
+{
+ int dim = f->dim;
+ EGLPNUM_TYPENAME_lc_info *lc_inf = f->lc_inf;
+ EGLPNUM_TYPENAME_lr_info *lr_inf = f->lr_inf;
+ EGLPNUM_TYPE *lrcoef = 0;
+ int *lrindx = 0;
+ EGLPNUM_TYPE *lccoef = f->lccoef;
+ int *lcindx = f->lcindx;
+ int nzcnt;
+ int beg;
+ int rnzcnt;
+ int rbeg;
+ int i;
+ int j;
+ int k;
+ int c;
+ int rval;
+
+ nzcnt = 0;
+ for (i = 0; i < dim; i++)
+ {
+ nzcnt += lc_inf[i].nzcnt;
+ lr_inf[i].nzcnt = 0;
+ lr_inf[i].delay = 0;
+ lc_inf[lc_inf[i].c].crank = i;
+ }
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (f->lrcoef);
+ if (nzcnt)
+ {
+ lrcoef = EGLPNUM_TYPENAME_EGlpNumAllocArray (nzcnt);
+ f->lrcoef = lrcoef;
+ }
+
+ ILL_IFFREE (f->lrindx, int);
+ ILL_SAFE_MALLOC (lrindx, nzcnt + 1, int);
+
+ f->lrindx = lrindx;
+
+ for (i = 0; i < dim; i++)
+ {
+ nzcnt = lc_inf[i].nzcnt;
+ beg = lc_inf[i].cbeg;
+ lc_inf[i].delay = 0;
+ for (j = 0; j < nzcnt; j++)
+ {
+ lr_inf[lc_inf[lcindx[beg + j]].crank].nzcnt++;
+ }
+ }
+
+ nzcnt = 0;
+ for (i = 0; i < dim; i++)
+ {
+ lr_inf[i].rbeg = nzcnt;
+ nzcnt += lr_inf[i].nzcnt;
+ lr_inf[i].nzcnt = 0;
+ lr_inf[i].r = lc_inf[i].c;
+ lr_inf[lr_inf[i].r].rrank = i;
+ }
+
+ for (i = 0; i < dim; i++)
+ {
+ nzcnt = lc_inf[i].nzcnt;
+ beg = lc_inf[i].cbeg;
+ c = lc_inf[i].c;
+ for (j = 0; j < nzcnt; j++)
+ {
+ k = lc_inf[lcindx[beg + j]].crank;
+ rbeg = lr_inf[k].rbeg;
+ rnzcnt = lr_inf[k].nzcnt;
+ lrindx[rbeg + rnzcnt] = c;
+ EGLPNUM_TYPENAME_EGlpNumCopy (lrcoef[rbeg + rnzcnt], lccoef[beg + j]);
+ lr_inf[k].nzcnt++;
+ }
+ }
+
+#ifdef TRACK_FACTOR
+ nzcnt = f->nzcnt_factor;
+ for (i = 0; i < dim; i++)
+ {
+ nzcnt += lc_inf[i].nzcnt;
+ }
+ f->nzcnt_factor = nzcnt;
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (f->maxelem_cur, f->maxelem_factor);
+ f->nzcnt_cur = f->nzcnt_factor;
+
+/*
+ dump_factor_stats (f);
+ QSlog("orig max %e nzcnt %d", f->maxelem_orig, f->nzcnt_orig);
+ QSlog("f maxelem %e nzcnt %d", f->maxelem_cur, f->nzcnt_cur);
+*/
+#endif /* TRACK_FACTOR */
+
+ rval = 0;
+
+CLEANUP:
+ EG_RETURN (rval);
+}
+
+static int handle_singularity (
+ EGLPNUM_TYPENAME_factor_work * f)
+{
+ int rval = 0;
+ int nsing;
+ int *singr = 0;
+ int *singc = 0;
+ int i;
+
+ if (f->p_nsing == 0 || f->p_singr == 0 || f->p_singc == 0)
+ {
+ QSlog("singular basis, but no place for singularity data");
+ return E_SING_NO_DATA;
+ }
+
+ nsing = f->nstages - f->stage;
+ ILL_SAFE_MALLOC (singr, nsing, int);
+ ILL_SAFE_MALLOC (singc, nsing, int);
+
+ for (i = f->stage; i < f->nstages; i++)
+ {
+ singr[i - f->stage] = f->rperm[i];
+ singc[i - f->stage] = f->cperm[i];
+ }
+ *f->p_nsing = nsing;
+ *f->p_singr = singr;
+ *f->p_singc = singc;
+ singr = 0;
+ singc = 0;
+
+CLEANUP:
+ ILL_IFFREE (singr, int);
+ ILL_IFFREE (singc, int);
+
+ EG_RETURN (rval);
+}
+
+static int dense_build_matrix (
+ EGLPNUM_TYPENAME_factor_work * f)
+{
+ EGLPNUM_TYPE *dmat = 0;
+ int stage = f->stage;
+ int drows = f->nstages - stage;
+ int dcols = f->dim - stage;
+ int dsize = drows * dcols;
+ int *crank = f->crank;
+ EGLPNUM_TYPE *urcoef = f->urcoef;
+ int *urindx = f->urindx;
+ int nzcnt;
+ int beg;
+ int i;
+ int r;
+ int j;
+ int rval = 0;
+
+ dmat = EGLPNUM_TYPENAME_EGlpNumAllocArray (dsize);
+
+ for (i = 0; i < dsize; i++)
+ EGLPNUM_TYPENAME_EGlpNumZero (dmat[i]);
+
+ for (i = 0; i < drows; i++)
+ {
+ r = f->rperm[i + stage];
+ nzcnt = f->ur_inf[r].nzcnt;
+ beg = f->ur_inf[r].rbeg;
+ for (j = 0; j < nzcnt; j++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (dmat[i * dcols - stage + crank[urindx[beg + j]]],
+ urcoef[beg + j]);
+ }
+ }
+
+ f->drows = drows;
+ f->dcols = dcols;
+ f->dense_base = f->stage;
+ f->dmat = dmat;
+ dmat = 0;
+
+//CLEANUP:
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (dmat);
+ EG_RETURN (rval);
+}
+
+static int dense_find_pivot (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int *p_r,
+ int *p_c)
+{
+ int dcols = f->dcols;
+ int drows = f->drows;
+ EGLPNUM_TYPE *dmat = f->dmat;
+ int dense_base = f->dense_base;
+ int s = f->stage - dense_base;
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+ int *rperm = f->rperm;
+ EGLPNUM_TYPE maxval;
+ int max_r;
+ int max_c;
+ int i;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (maxval);
+ EGLPNUM_TYPENAME_EGlpNumZero (maxval);
+ max_r = -1;
+ for (i = s; i < drows; i++)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (maxval, ur_inf[rperm[dense_base + i]].max))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (maxval, ur_inf[rperm[dense_base + i]].max);
+ max_r = i;
+ }
+ }
+ if (max_r == -1)
+ {
+ return E_NO_PIVOT;
+ }
+
+ EGLPNUM_TYPENAME_EGlpNumZero (maxval);
+ max_c = -1;
+ for (i = s; i < drows; i++)
+ {
+ EGlpNumSetToMaxAbsAndDo (maxval, dmat[max_r * dcols + i], max_c = i);
+ }
+ if (max_c == -1)
+ {
+ return E_NO_PIVOT;
+ }
+ *p_r = max_r;
+ *p_c = max_c;
+
+ EGLPNUM_TYPENAME_EGlpNumClearVar (maxval);
+ return 0;
+}
+
+static void dense_swap (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int r,
+ int c)
+{
+ int dcols = f->dcols;
+ int drows = f->drows;
+ EGLPNUM_TYPE *dmat = f->dmat;
+ int dense_base = f->dense_base;
+ int s = f->stage - dense_base;
+ int i;
+ EGLPNUM_TYPE v;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+ if (r != s)
+ {
+ ILL_SWAP (f->rperm[dense_base + s], f->rperm[dense_base + r], i);
+ f->rrank[f->rperm[dense_base + s]] = dense_base + s;
+ f->rrank[f->rperm[dense_base + r]] = dense_base + r;
+ for (i = 0; i < dcols; i++)
+ {
+ EGLPNUM_TYPENAME_EGLPNUM_SWAP (dmat[s * dcols + i], dmat[r * dcols + i], v);
+ }
+ }
+ if (c != s)
+ {
+ ILL_SWAP (f->cperm[dense_base + s], f->cperm[dense_base + c], i);
+ f->crank[f->cperm[dense_base + s]] = dense_base + s;
+ f->crank[f->cperm[dense_base + c]] = dense_base + c;
+ for (i = 0; i < drows; i++)
+ {
+ EGLPNUM_TYPENAME_EGLPNUM_SWAP (dmat[i * dcols + s], dmat[i * dcols + c], v);
+ }
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+
+static void dense_elim (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int r,
+ int c)
+{
+ int dcols = f->dcols;
+ int drows = f->drows;
+ EGLPNUM_TYPE *dmat = f->dmat;
+ int dense_base = f->dense_base;
+ int s = f->stage - dense_base;
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+ int *rperm = f->rperm;
+ int i;
+ int j;
+ EGLPNUM_TYPE pivval;
+ EGLPNUM_TYPE max;
+ EGLPNUM_TYPE v;
+ EGLPNUM_TYPE w;
+
+#ifdef TRACK_FACTOR
+ EGLPNUM_TYPE maxelem_factor;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (maxelem_factor);
+ EGLPNUM_TYPENAME_EGlpNumCopy (maxelem_factor, f->maxelem_factor);
+#endif
+ EGLPNUM_TYPENAME_EGlpNumInitVar (pivval);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (max);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (w);
+
+ dense_swap (f, r, c);
+ f->stage++;
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (pivval, EGLPNUM_TYPENAME_oneLpNum, dmat[s * dcols + s]);
+ for (i = s + 1; i < drows; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (v, dmat[i * dcols + s]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (v))
+ {
+ EGLPNUM_TYPENAME_EGlpNumMultTo (v, pivval);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (v, f->fzero_tol))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (dmat[i * dcols + s], v);
+#ifdef TRACK_FACTOR
+ EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (maxelem_factor, v);
+#endif
+ EGLPNUM_TYPENAME_EGlpNumZero (max);
+ for (j = s + 1; j < drows; j++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (w, dmat[i * dcols + j]);
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (w, v, dmat[s * dcols + j]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (dmat[i * dcols + j], w);
+ EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (max, w);
+ }
+ for (j = drows; j < dcols; j++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (w, dmat[i * dcols + j]);
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (w, v, dmat[s * dcols + j]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (dmat[i * dcols + j], w);
+ }
+ EGLPNUM_TYPENAME_EGlpNumCopy (ur_inf[rperm[dense_base + i]].max, max);
+#ifdef TRACK_FACTOR
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (maxelem_factor, max))
+ EGLPNUM_TYPENAME_EGlpNumCopy (maxelem_factor, max);
+#endif
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumZero (dmat[i * dcols + s]);
+ }
+ }
+ }
+#ifdef TRACK_FACTOR
+ EGLPNUM_TYPENAME_EGlpNumCopy (f->maxelem_factor, maxelem_factor);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (maxelem_factor);
+#endif
+ EGLPNUM_TYPENAME_EGlpNumClearVar (pivval);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (max);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (w);
+}
+
+static int dense_replace_row (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int i)
+{
+ int dcols = f->dcols;
+ int dense_base = f->dense_base;
+ EGLPNUM_TYPE *dmat = f->dmat + i * dcols;
+ EGLPNUM_TYPE *urcoef;
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+ int *cperm = f->cperm;
+ int r = f->rperm[dense_base + i];
+ int *urindx;
+ int nzcnt;
+ int beg;
+ int j;
+ int rval = 0;
+
+ nzcnt = 0;
+ for (j = i; j < dcols; j++)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (dmat[j], f->fzero_tol))
+ {
+ nzcnt++;
+ }
+ }
+ if (nzcnt > ur_inf[r].nzcnt)
+ {
+ if (ur_inf[r].rbeg + ur_inf[r].nzcnt == f->ur_freebeg)
+ {
+ f->ur_freebeg = ur_inf[r].rbeg;
+ }
+ ur_inf[r].nzcnt = 0;
+ if (f->ur_freebeg + nzcnt > f->ur_space)
+ {
+ rval = make_ur_space (f, nzcnt);
+ CHECKRVALG (rval, CLEANUP);
+ }
+ ur_inf[r].rbeg = f->ur_freebeg;
+ f->ur_freebeg += nzcnt;
+ }
+ beg = ur_inf[r].rbeg;
+ urcoef = f->urcoef;
+ urindx = f->urindx;
+ for (j = i; j < dcols; j++)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (dmat[j], f->fzero_tol))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (urcoef[beg], dmat[j]);
+ urindx[beg] = cperm[dense_base + j];
+ beg++;
+ }
+ }
+ ur_inf[r].nzcnt = beg - ur_inf[r].rbeg;
+CLEANUP:
+ EG_RETURN (rval);
+}
+
+static int dense_create_col (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int i)
+{
+ int dcols = f->dcols;
+ int drows = f->drows;
+ int dense_base = f->dense_base;
+ EGLPNUM_TYPE *dmat = f->dmat;
+ EGLPNUM_TYPE *lccoef;
+ EGLPNUM_TYPENAME_lc_info *lc_inf = f->lc_inf;
+ int *rperm = f->rperm;
+ int *lcindx;
+ int nzcnt;
+ int beg;
+ int j;
+ int rval = 0;
+
+ nzcnt = 0;
+ for (j = i + 1; j < drows; j++)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (dmat[j * dcols + i], f->fzero_tol))
+ {
+ nzcnt++;
+ }
+ }
+
+ if (f->lc_freebeg + nzcnt >= f->lc_space)
+ {
+ rval = make_lc_space (f, nzcnt);
+ CHECKRVALG (rval, CLEANUP);
+ }
+ beg = f->lc_freebeg;
+ lc_inf[dense_base + i].cbeg = beg;
+ lc_inf[dense_base + i].c = rperm[dense_base + i];
+ lcindx = f->lcindx;
+ lccoef = f->lccoef;
+
+ for (j = i + 1; j < drows; j++)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (dmat[j * dcols + i], f->fzero_tol))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (lccoef[beg], dmat[j * dcols + i]);
+ lcindx[beg] = rperm[dense_base + j];
+ beg++;
+ }
+ }
+ lc_inf[dense_base + i].nzcnt = beg - lc_inf[dense_base + i].cbeg;
+ f->lc_freebeg = beg;
+CLEANUP:
+ EG_RETURN (rval);
+}
+
+static int dense_replace (
+ EGLPNUM_TYPENAME_factor_work * f)
+{
+ int drows = f->drows;
+ int rval = 0;
+ int i;
+
+ for (i = 0; i < drows; i++)
+ {
+ rval = dense_replace_row (f, i);
+ CHECKRVALG (rval, CLEANUP);
+ rval = dense_create_col (f, i);
+ CHECKRVALG (rval, CLEANUP);
+ }
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (f->dmat);
+ f->drows = 0;
+ f->dcols = 0;
+CLEANUP:
+ EG_RETURN (rval);
+}
+
+static int dense_factor (
+ EGLPNUM_TYPENAME_factor_work * f)
+{
+ int r;
+ int c;
+ int rval = 0;
+
+#ifdef TRACK_FACTOR
+#ifdef NOTICE_BLOWUP
+ double tmpsize;
+#endif
+#endif
+
+/*
+ QSlog("dense kernel, %d rows, %d cols...", f->nstages - f->stage,
+ f->dim - f->stage);
+*/
+
+ rval = dense_build_matrix (f);
+ CHECKRVALG (rval, CLEANUP);
+
+#ifdef FACTOR_DEBUG
+#if (FACTOR_DEBUG+0>1)
+ MESSAGE (0,"before Dense EGLPNUM_TYPENAME_ILLfactor");
+ dump_matrix (f, 1);
+#endif
+#endif
+
+ while (f->stage < f->nstages)
+ {
+ r = f->stage - f->dense_base;
+ rval = dense_find_pivot (f, &r, &c);
+ if (rval == E_NO_PIVOT)
+ {
+ rval = handle_singularity (f);
+ CHECKRVALG (rval, CLEANUP);
+ return E_SINGULAR_INTERNAL;
+ }
+ else
+ {
+ CHECKRVALG (rval, CLEANUP);
+ }
+#ifdef FACTOR_DEBUG
+#if (FACTOR_DEBUG+0>2)
+ MESSAGE (0,"dense pivot elem: %d %d", r, c);
+#endif
+#endif /* FACTOR_DEBUG */
+ dense_elim (f, r, c);
+
+#ifdef TRACK_FACTOR
+#ifdef NOTICE_BLOWUP
+ tmpsize = f->maxmult * EGLPNUM_TYPENAME_EGlpNumToLf (f->maxelem_orig);
+ if (tmpsize < EGLPNUM_TYPENAME_EGlpNumToLf (f->maxelem_factor) &&
+ EGLPNUM_TYPENAME_EGlpNumIsLess (f->partial_cur, EGLPNUM_TYPENAME_oneLpNum))
+ {
+ return E_FACTOR_BLOWUP;
+ }
+#endif /* NOTICE_BLOWUP */
+#endif /* TRACK_FACTOR */
+
+#ifdef FACTOR_DEBUG
+#if (FACTOR_DEBUG+0>1)
+ MESSAGE (0,"After dense pivot stage %d (%d) of %d (%d)",
+ f->stage - f->dense_base, f->stage,
+ f->nstages - f->dense_base, f->nstages);
+#endif
+#if (FACTOR_DEBUG+0>2)
+ dump_matrix (f, 1);
+#endif
+#endif /* FACTOR_DEBUG */
+ }
+
+#ifdef FACTOR_DEBUG
+ MESSAGE (0,"After dense EGLPNUM_TYPENAME_ILLfactor:\n");
+ dump_matrix (f, 0);
+#endif /* FACTOR_DEBUG */
+
+ rval = dense_replace (f);
+ CHECKRVALG (rval, CLEANUP);
+
+#ifdef FACTOR_DEBUG
+ MESSAGE (0,"After replacement:\n");
+ dump_matrix (f, 0);
+#endif /* FACTOR_DEBUG */
+
+CLEANUP:
+ EG_RETURN (rval);
+}
+
+#ifdef RECORD
+EGioFile_t *fsave = 0;
+int fsavecnt = 0;
+#endif /* RECORD */
+
+static int ILLfactor_try (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int *basis,
+ int *cbeg,
+ int *clen,
+ int *cindx,
+ EGLPNUM_TYPE * ccoef)
+{
+ int rval = 0;
+ int r;
+ int c;
+
+#ifdef TRACK_FACTOR
+#ifdef NOTICE_BLOWUP
+ EGLPNUM_TYPE tmpsize;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (tmpsize);
+#endif
+#endif
+
+#ifdef RECORD
+ {
+ int ncol = 0;
+ int nzcnt = 0;
+ int dim = f->dim;
+ int i;
+ int j;
+ char fnambuf[40];
+
+ for (i = 0; i < dim; i++)
+ {
+ if (basis[i] > ncol)
+ ncol = basis[i];
+ }
+ ncol++;
+ for (i = 0; i < ncol; i++)
+ {
+ nzcnt += clen[i];
+ }
+ if (fsave)
+ EGioClose (fsave);
+#if HAVE_LIBZ
+ sprintf (fnambuf, "prob.mat.%d.gz", fsavecnt);
+#elif HAVE_LIBBZ2
+ sprintf (fnambuf, "prob.mat.%d.bz2", fsavecnt);
+#else
+ sprintf (fnambuf, "prob.mat.%d", fsavecnt);
+#endif
+ fsavecnt++;
+ fsave = EGioOpen (fnambuf, "w");
+ EGioPrintf (fsave, "%d %d %d\n", f->dim, ncol, nzcnt);
+ for (i = 0; i < dim; i++)
+ {
+ EGioPrintf (fsave, "%d ", basis[i]);
+ }
+ EGioPrintf (fsave, "\n");
+ for (i = 0; i < ncol; i++)
+ {
+ EGioPrintf (fsave, "%d", clen[i]);
+ for (j = 0; j < clen[i]; j++)
+ {
+ EGioPrintf (fsave, " %d %.16lg", cindx[cbeg[i] + j],
+ EGLPNUM_TYPENAME_EGlpNumToLf (ccoef[cbeg[i] + j]));
+ }
+ EGioPrintf (fsave, "\n");
+ }
+ EGioPrintf (fsave, "\n");
+ EGioFlush (fsave);
+ }
+#endif /* RECORD */
+
+ rval = init_matrix (f, basis, cbeg, clen, cindx, ccoef);
+ CHECKRVALG (rval, CLEANUP);
+
+ f->stage = 0;
+ f->nstages = f->dim;
+
+#ifdef FACTOR_DEBUG
+ MESSAGE (0,"Initial matrix:");
+#if (FACTOR_DEBUG+0>1)
+ dump_matrix (f, 0);
+#endif
+#endif /* FACTOR_DEBUG */
+#ifdef FACTOR_STATS
+ QSlog("Initial matrix: ");
+ dump_factor_stats (f);
+#endif /* FACTOR_STATS */
+
+ while (f->stage < f->nstages)
+ {
+ rval = find_pivot (f, &r, &c);
+ if (rval == E_NO_PIVOT)
+ {
+ rval = handle_singularity (f);
+ CHECKRVALG (rval, CLEANUP);
+ return 0;
+ }
+ else
+ {
+ CHECKRVALG (rval, CLEANUP);
+ }
+ if (f->ur_inf[r].pivcnt > f->dense_fract * (f->nstages - f->stage) &&
+ f->uc_inf[c].nzcnt > f->dense_fract * (f->nstages - f->stage) &&
+ f->nstages - f->stage > f->dense_min)
+ {
+ rval = dense_factor (f);
+ if (rval == E_SINGULAR_INTERNAL)
+ return 0;
+ if (rval)
+ return rval;
+ break;
+ }
+#ifdef FACTOR_DEBUG
+ MESSAGE (0,"pivot elem: %d %d", r, c);
+#endif /* FACTOR_DEBUG */
+ rval = elim (f, r, c);
+ CHECKRVALG (rval, CLEANUP);
+
+#ifdef TRACK_FACTOR
+#ifdef NOTICE_BLOWUP
+ EGLPNUM_TYPENAME_EGlpNumSet (tmpsize, f->maxmult);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (tmpsize, f->maxelem_orig);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (tmpsize, f->maxelem_factor) &&
+ EGLPNUM_TYPENAME_EGlpNumIsLess (f->partial_cur, EGLPNUM_TYPENAME_oneLpNum))
+ {
+ return E_FACTOR_BLOWUP;
+ }
+#endif /* NOTICE_BLOWUP */
+#endif /* TRACK_FACTOR */
+
+#ifdef FACTOR_DEBUG
+#if (FACTOR_DEBUG+0>3)
+ MESSAGE (0,"After pivot stage %d of %d", f->stage, f->nstages);
+ dump_matrix (f, 0);
+#endif
+#endif /* FACTOR_DEBUG */
+ }
+
+ rval = build_iteration_u_data (f);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = build_iteration_l_data (f);
+ CHECKRVALG (rval, CLEANUP);
+
+#ifdef TRACK_FACTOR
+#ifdef NOTICE_BLOWUP
+ EGLPNUM_TYPENAME_EGlpNumSet (tmpsize, f->minmult);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (tmpsize, f->maxelem_orig);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (f->maxelem_factor, tmpsize) &&
+ EGLPNUM_TYPENAME_EGlpNumIsLess (f->partial_tol, f->partial_cur))
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsGreaDbl (f->partial_cur, 0.5))
+ {
+ EGLPNUM_TYPENAME_EGlpNumSet (f->partial_cur, 0.5);
+ }
+ else if (EGLPNUM_TYPENAME_EGlpNumIsGreaDbl (f->partial_cur, 0.25))
+ {
+ EGLPNUM_TYPENAME_EGlpNumSet (f->partial_cur, 0.25);
+ }
+ else if (EGLPNUM_TYPENAME_EGlpNumIsGreaDbl (f->partial_cur, 0.1))
+ {
+ EGLPNUM_TYPENAME_EGlpNumSet (f->partial_cur, 0.1);
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumDivUiTo (f->partial_cur, 10);
+ }
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (f->partial_cur, f->partial_tol))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (f->partial_cur, f->partial_tol);
+ }
+/* Bico - comment out for dist
+ QSlog("factor good, lowering partial tolerance to %.2f",
+ f->partial_cur);
+*/
+ }
+#endif /* NOTICE_BLOWUP */
+#endif /* TRACK_FACTOR */
+
+#ifdef FACTOR_DEBUG
+ MESSAGE(0,"Factored matrix:");
+#if (FACTOR_DEBUG+0>1)
+ dump_matrix (f, 0);
+#endif
+#endif /* FACTOR_DEBUG */
+
+#ifdef FACTOR_STATS
+ QSlog("Factored matrix: ");
+ dump_factor_stats (f);
+#endif /* FACTOR_STATS */
+CLEANUP:
+#ifdef TRACK_FACTOR
+#ifdef NOTICE_BLOWUP
+ EGLPNUM_TYPENAME_EGlpNumClearVar (tmpsize);
+#endif
+#endif
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLfactor (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int *basis,
+ int *cbeg,
+ int *clen,
+ int *cindx,
+ EGLPNUM_TYPE * ccoef,
+ int *p_nsing,
+ int **p_singr,
+ int **p_singc)
+{
+ int rval;
+
+ f->p_nsing = p_nsing;
+ f->p_singr = p_singr;
+ f->p_singc = p_singc;
+ *p_nsing = 0;
+
+AGAIN:
+ rval = ILLfactor_try (f, basis, cbeg, clen, cindx, ccoef);
+ if (rval == E_FACTOR_BLOWUP)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessDbl (f->partial_cur, 0.1))
+ {
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (f->partial_cur, 10);
+ }
+ else if (EGLPNUM_TYPENAME_EGlpNumIsLessDbl (f->partial_cur, 0.25))
+ {
+ EGLPNUM_TYPENAME_EGlpNumSet (f->partial_cur, 0.25);
+ }
+ else if (EGLPNUM_TYPENAME_EGlpNumIsLessDbl (f->partial_cur, 0.5))
+ {
+ EGLPNUM_TYPENAME_EGlpNumSet (f->partial_cur, 0.5);
+ }
+ else if (EGLPNUM_TYPENAME_EGlpNumIsLess (f->partial_cur, EGLPNUM_TYPENAME_oneLpNum))
+ {
+ EGLPNUM_TYPENAME_EGlpNumOne (f->partial_cur);
+ }
+ else
+ {
+ EG_RETURN (rval);
+ }
+/* Bico - comment out for dist
+ QSlog("factor blowup, changing partial tolerance to %.2f",
+ f->partial_cur);
+*/
+ goto AGAIN;
+ }
+ EG_RETURN (rval);
+}
+
+static void ILLfactor_ftranl (
+ EGLPNUM_TYPENAME_factor_work * f,
+ EGLPNUM_TYPE * a)
+{
+ int *lcindx = f->lcindx;
+ EGLPNUM_TYPENAME_lc_info *lc_inf = f->lc_inf;
+ EGLPNUM_TYPE *lccoef = f->lccoef;
+ int dim = f->dim;
+ int beg;
+ int nzcnt;
+ int i;
+ int j;
+ EGLPNUM_TYPE v;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+ for (i = 0; i < dim; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (v, a[lc_inf[i].c]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (v))
+ {
+ nzcnt = lc_inf[i].nzcnt;
+ beg = lc_inf[i].cbeg;
+ for (j = 0; j < nzcnt; j++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (a[lcindx[beg + j]], v, lccoef[beg + j]);
+ }
+ }
+#ifdef SOLVE_DEBUG
+#if (SOLVE_DEBUG+0 > 1)
+ QSlog("EGLPNUM_TYPENAME_ILLfactor_ftran a after l %d:", i);
+ for (j = 0; j < f->dim; j++)
+ {
+ QSlog(" %.3f", EGLPNUM_TYPENAME_EGlpNumToLf (a[j]));
+ }
+ MESSAGE(0," ");
+#endif
+#endif /* SOLVE_DEBUG */
+ }
+#ifdef SOLVE_DEBUG
+#if (SOLVE_DEBUG+0 <= 1)
+ QSlog("EGLPNUM_TYPENAME_ILLfactor_ftran a after l:");
+ for (j = 0; j < f->dim; j++)
+ {
+ QSlog(" %.3f", EGLPNUM_TYPENAME_EGlpNumToLf (a[j]));
+ }
+#endif
+#endif /* SOLVE_DEBUG */
+ EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+
+#if 0
+static void ftranl3_delay (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int c)
+{
+ EGLPNUM_TYPENAME_lc_info *lc_inf = f->lc_inf;
+ int nzcnt;
+ int *indx;
+ int i;
+
+ c = lc_inf[c].crank;
+ nzcnt = lc_inf[c].nzcnt;
+ indx = f->lcindx + lc_inf[c].cbeg;
+ for (i = 0; i < nzcnt; i++)
+ {
+ c = indx[i];
+ if (lc_inf[c].delay++ == 0)
+ {
+ ftranl3_delay (f, c);
+ }
+ }
+}
+#endif
+
+static void ftranl3_delay2 (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int c)
+{
+ EGLPNUM_TYPENAME_lc_info *lc_inf = f->lc_inf;
+ int nzcnt;
+ int *indx;
+ int i;
+ int last;
+
+ do
+ {
+ c = lc_inf[c].crank;
+ nzcnt = lc_inf[c].nzcnt;
+ indx = f->lcindx + lc_inf[c].cbeg;
+ last = -1;
+ for (i = 0; i < nzcnt; i++)
+ {
+ c = indx[i];
+ if (lc_inf[c].delay++ == 0)
+ {
+ if (last >= 0)
+ {
+ ftranl3_delay2 (f, last);
+ }
+ last = c;
+ }
+ }
+ c = last;
+ } while (c >= 0);
+}
+
+#if 0
+static void ftranl3_process (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int c,
+ EGLPNUM_TYPENAME_svector * x)
+{
+ EGLPNUM_TYPENAME_lc_info *lc_inf = f->lc_inf;
+ EGLPNUM_TYPE *work = f->work_coef;
+ int nzcnt;
+ int *indx;
+ int i;
+ EGLPNUM_TYPE *coef;
+ EGLPNUM_TYPE v;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (v, work[c]);
+ EGLPNUM_TYPENAME_EGlpNumZero (work[c]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (v))
+ {
+ x->indx[x->nzcnt] = c;
+ EGLPNUM_TYPENAME_EGlpNumCopy (x->coef[x->nzcnt], v);
+ x->nzcnt++;
+ }
+ c = lc_inf[c].crank;
+ nzcnt = lc_inf[c].nzcnt;
+ indx = f->lcindx + lc_inf[c].cbeg;
+ coef = f->lccoef + lc_inf[c].cbeg;
+ for (i = 0; i < nzcnt; i++)
+ {
+ c = indx[i];
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (work[c], v, coef[i]);
+ if (--lc_inf[c].delay == 0)
+ {
+ ftranl3_process (f, c, x);
+ }
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+#endif
+
+static void ftranl3_process2 (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int c,
+ EGLPNUM_TYPENAME_svector * x)
+{
+ EGLPNUM_TYPENAME_lc_info *lc_inf = f->lc_inf;
+ EGLPNUM_TYPE *work = f->work_coef;
+ int nzcnt;
+ int *indx;
+ EGLPNUM_TYPE *coef;
+ int i;
+ int last;
+ EGLPNUM_TYPE v;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+ do
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (v, work[c]);
+ EGLPNUM_TYPENAME_EGlpNumZero (work[c]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (v))
+ {
+ x->indx[x->nzcnt] = c;
+ EGLPNUM_TYPENAME_EGlpNumCopy (x->coef[x->nzcnt], v);
+ x->nzcnt++;
+ }
+ c = lc_inf[c].crank;
+ nzcnt = lc_inf[c].nzcnt;
+ indx = f->lcindx + lc_inf[c].cbeg;
+ coef = f->lccoef + lc_inf[c].cbeg;
+ last = -1;
+ for (i = 0; i < nzcnt; i++)
+ {
+ c = indx[i];
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (work[c], v, coef[i]);
+ if (--lc_inf[c].delay == 0)
+ {
+ if (last >= 0)
+ {
+ ftranl3_process2 (f, last, x);
+ }
+ last = c;
+ }
+ }
+ c = last;
+ } while (c >= 0);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+
+static void ILLfactor_ftranl3 (
+ EGLPNUM_TYPENAME_factor_work * f,
+ EGLPNUM_TYPENAME_svector * a,
+ EGLPNUM_TYPENAME_svector * x)
+{
+ EGLPNUM_TYPE *work = f->work_coef;
+ int anzcnt = a->nzcnt;
+ int *aindx = a->indx;
+ EGLPNUM_TYPE *acoef = a->coef;
+ EGLPNUM_TYPENAME_lc_info *lc_inf = f->lc_inf;
+ int i;
+
+ for (i = 0; i < anzcnt; i++)
+ {
+ if (lc_inf[aindx[i]].delay++ == 0)
+ {
+ ftranl3_delay2 (f, aindx[i]);
+ }
+ EGLPNUM_TYPENAME_EGlpNumCopy (work[aindx[i]], acoef[i]);
+ }
+ x->nzcnt = 0;
+ for (i = 0; i < anzcnt; i++)
+ {
+ if (--lc_inf[aindx[i]].delay == 0)
+ {
+ ftranl3_process2 (f, aindx[i], x);
+ }
+ }
+#ifdef SOLVE_DEBUG
+ QSlog("EGLPNUM_TYPENAME_ILLfactor_ftran x after l3:");
+ for (i = 0; i < x->nzcnt; i++)
+ {
+ QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (x->coef[i]), x->indx[i]);
+ }
+#endif /* SOLVE_DEBUG */
+}
+
+static void ILLfactor_ftrane (
+ EGLPNUM_TYPENAME_factor_work * f,
+ EGLPNUM_TYPE * a)
+{
+ int *erindx = f->erindx;
+ EGLPNUM_TYPE *ercoef = f->ercoef;
+ EGLPNUM_TYPENAME_er_info *er_inf = f->er_inf;
+ int etacnt = f->etacnt;
+ int beg;
+ int nzcnt;
+ int i;
+ int j;
+ EGLPNUM_TYPE v;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+ for (i = 0; i < etacnt; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (v, a[er_inf[i].r]);
+ nzcnt = er_inf[i].nzcnt;
+ beg = er_inf[i].rbeg;
+ for (j = 0; j < nzcnt; j++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (v, ercoef[beg + j], a[erindx[beg + j]]);
+ }
+ EGLPNUM_TYPENAME_EGlpNumCopy (a[er_inf[i].r], v);
+#ifdef SOLVE_DEBUG
+#if (SOLVE_DEBUG+0 > 1)
+ QSlog("EGLPNUM_TYPENAME_ILLfactor_ftran a after eta %d:", i);
+ for (j = 0; j < f->dim; j++)
+ {
+ QSlog(" %.3f", EGLPNUM_TYPENAME_EGlpNumToLf (a[j]));
+ }
+#endif
+#endif /* SOLVE_DEBUG */
+ }
+#ifdef SOLVE_DEBUG
+#if (SOLVE_DEBUG+0 <= 1)
+ QSlog("EGLPNUM_TYPENAME_ILLfactor_ftran a after eta:");
+ for (j = 0; j < f->dim; j++)
+ {
+ QSlog(" %.3f", EGLPNUM_TYPENAME_EGlpNumToLf (a[j]));
+ }
+#endif
+#endif /* SOLVE_DEBUG */
+ EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+
+static void ILLfactor_ftrane2 (
+ EGLPNUM_TYPENAME_factor_work * f,
+ EGLPNUM_TYPENAME_svector * a)
+{
+ int *erindx = f->erindx;
+ EGLPNUM_TYPE *ercoef = f->ercoef;
+ EGLPNUM_TYPENAME_er_info *er_inf = f->er_inf;
+ int etacnt = f->etacnt;
+ int beg;
+ int nzcnt;
+ int anzcnt = a->nzcnt;
+ int *aindx = a->indx;
+ EGLPNUM_TYPE *acoef = a->coef;
+ EGLPNUM_TYPE *work_coef = f->work_coef;
+ int *work_indx = f->work_indx;
+ int i;
+ int j;
+ int r;
+ EGLPNUM_TYPE v;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+ for (i = 0; i < anzcnt; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
+ work_indx[aindx[i]] = i + 1;
+ }
+ for (i = 0; i < etacnt; i++)
+ {
+ r = er_inf[i].r;
+ EGLPNUM_TYPENAME_EGlpNumCopy (v, work_coef[r]);
+ nzcnt = er_inf[i].nzcnt;
+ beg = er_inf[i].rbeg;
+ for (j = 0; j < nzcnt; j++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (v, ercoef[beg + j], work_coef[erindx[beg + j]]);
+ }
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (v))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (work_coef[r], v);
+ if (work_indx[r] == 0)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (acoef[anzcnt], v);
+ aindx[anzcnt] = r;
+ work_indx[r] = anzcnt + 1;
+ anzcnt++;
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (acoef[work_indx[r] - 1], v);
+ }
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumZero (work_coef[r]);
+ if (work_indx[r])
+ {
+ EGLPNUM_TYPENAME_EGlpNumZero (acoef[work_indx[r] - 1]);
+ }
+ }
+#ifdef SOLVE_DEBUG
+#if (SOLVE_DEBUG+0 > 1)
+ QSlog("EGLPNUM_TYPENAME_ILLfactor_ftran a after eta2 %d:", i);
+ for (j = 0; j < anzcnt; j++)
+ {
+ QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (acoef[j]), aindx[j]);
+ }
+#endif
+#endif /* SOLVE_DEBUG */
+ }
+ i = 0;
+ while (i < anzcnt)
+ {
+ EGLPNUM_TYPENAME_EGlpNumZero (work_coef[aindx[i]]);
+ work_indx[aindx[i]] = 0;
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (acoef[i], f->fzero_tol))
+ {
+ /*if (acoef[i] > fzero_tol || acoef[i] < -fzero_tol) */
+ i++;
+ }
+ else
+ {
+ --anzcnt;
+ EGLPNUM_TYPENAME_EGlpNumCopy (acoef[i], acoef[anzcnt]);
+ aindx[i] = aindx[anzcnt];
+ }
+ }
+ a->nzcnt = anzcnt;
+
+#ifdef SOLVE_DEBUG
+#if (SOLVE_DEBUG+0 <= 1)
+ QSlog("EGLPNUM_TYPENAME_ILLfactor_ftran a after eta2:");
+ for (j = 0; j < anzcnt; j++)
+ {
+ QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (acoef[j]), aindx[j]);
+ }
+#endif
+#endif /* SOLVE_DEBUG */
+ EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+
+static void ILLfactor_ftranu (
+ EGLPNUM_TYPENAME_factor_work * f,
+ EGLPNUM_TYPE * a,
+ EGLPNUM_TYPENAME_svector * x)
+{
+ int *ucindx = f->ucindx;
+ EGLPNUM_TYPE *uccoef = f->uccoef;
+ EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+ int *cperm = f->cperm;
+ int *rperm = f->rperm;
+ int dim = f->dim;
+ int xnzcnt = 0;
+ int *xindx = x->indx;
+ EGLPNUM_TYPE *xcoef = x->coef;
+ int nzcnt;
+ int beg;
+ int i;
+ int j;
+ EGLPNUM_TYPE v;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+ for (i = dim - 1; i >= 0; i--)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (v, a[rperm[i]]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (v)) /*((v = a[rperm[i]]) != 0.0) */
+ {
+ j = cperm[i];
+ beg = uc_inf[j].cbeg;
+ EGLPNUM_TYPENAME_EGlpNumDivTo (v, uccoef[beg]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (v, f->szero_tol))
+ {
+ /*if (v > szero_tol || v < -szero_tol) */
+ xindx[xnzcnt] = j;
+ EGLPNUM_TYPENAME_EGlpNumCopy (xcoef[xnzcnt], v);
+ xnzcnt++;
+ }
+ nzcnt = uc_inf[j].nzcnt;
+ for (j = 1; j < nzcnt; j++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (a[ucindx[beg + j]], v, uccoef[beg + j]);
+ }
+ EGLPNUM_TYPENAME_EGlpNumZero (a[rperm[i]]);
+ }
+ }
+ x->nzcnt = xnzcnt;
+#ifdef SOLVE_DEBUG
+ QSlog("EGLPNUM_TYPENAME_ILLfactor_ftran x after u:");
+ for (j = 0; j < x->nzcnt; j++)
+ {
+ QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (x->coef[j]), x->indx[j]);
+ }
+#endif /* SOLVE_DEBUG */
+ EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+
+
+#if 0
+static void ftranu3_delay (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int c)
+{
+ EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+ int nzcnt;
+ int *indx;
+ int i;
+
+ c = f->cperm[f->rrank[c]];
+ nzcnt = uc_inf[c].nzcnt;
+ indx = f->ucindx + uc_inf[c].cbeg;
+ for (i = 1; i < nzcnt; i++)
+ {
+ c = indx[i];
+ if (uc_inf[c].delay++ == 0)
+ {
+ ftranu3_delay (f, c);
+ }
+ }
+}
+#endif
+
+static void ftranu3_delay2 (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int c)
+{
+ EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+ int nzcnt;
+ int *indx;
+ int i;
+ int last;
+
+ do
+ {
+ c = f->cperm[f->rrank[c]];
+ nzcnt = uc_inf[c].nzcnt;
+ indx = f->ucindx + uc_inf[c].cbeg;
+ last = -1;
+ for (i = 1; i < nzcnt; i++)
+ {
+ c = indx[i];
+ if (uc_inf[c].delay++ == 0)
+ {
+ if (last >= 0)
+ {
+ ftranu3_delay2 (f, last);
+ }
+ last = c;
+ }
+ }
+ c = last;
+ } while (c >= 0);
+}
+
+#if 0
+static void ftranu3_process (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int c,
+ EGLPNUM_TYPENAME_svector * x)
+{
+ EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+ EGLPNUM_TYPE *work = f->work_coef;
+ int nzcnt;
+ int *indx;
+ EGLPNUM_TYPE *coef;
+ int i;
+ EGLPNUM_TYPE v;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (v, work[c]);
+ EGLPNUM_TYPENAME_EGlpNumZero (work[c]);
+ c = f->cperm[f->rrank[c]];
+ nzcnt = uc_inf[c].nzcnt;
+ indx = f->ucindx + uc_inf[c].cbeg;
+ coef = f->uccoef + uc_inf[c].cbeg;
+ EGLPNUM_TYPENAME_EGlpNumDivTo (v, coef[0]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (v, f->szero_tol))
+ /*if (v > szero_tol || v < -szero_tol) */
+ {
+ x->indx[x->nzcnt] = c;
+ EGLPNUM_TYPENAME_EGlpNumCopy (x->coef[x->nzcnt], v);
+ x->nzcnt++;
+ }
+ for (i = 1; i < nzcnt; i++)
+ {
+ c = indx[i];
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (work[c], v, coef[i]);
+ if (--uc_inf[c].delay == 0)
+ {
+ ftranu3_process (f, c, x);
+ }
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+#endif
+
+static void ftranu3_process2 (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int c,
+ EGLPNUM_TYPENAME_svector * x)
+{
+ EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+ EGLPNUM_TYPE *work = f->work_coef;
+ int nzcnt;
+ int *indx;
+ EGLPNUM_TYPE *coef;
+ int i;
+ int last;
+ EGLPNUM_TYPE v;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+ do
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (v, work[c]);
+ EGLPNUM_TYPENAME_EGlpNumZero (work[c]);
+ c = f->cperm[f->rrank[c]];
+ nzcnt = uc_inf[c].nzcnt;
+ indx = f->ucindx + uc_inf[c].cbeg;
+ coef = f->uccoef + uc_inf[c].cbeg;
+ EGLPNUM_TYPENAME_EGlpNumDivTo (v, coef[0]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (v, f->szero_tol))
+ /*if (v > szero_tol || v < -szero_tol) */
+ {
+ x->indx[x->nzcnt] = c;
+ EGLPNUM_TYPENAME_EGlpNumCopy (x->coef[x->nzcnt], v);
+ x->nzcnt++;
+ }
+ last = -1;
+ for (i = 1; i < nzcnt; i++)
+ {
+ c = indx[i];
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (work[c], v, coef[i]);
+ if (--uc_inf[c].delay == 0)
+ {
+ if (last >= 0)
+ {
+ ftranu3_process2 (f, last, x);
+ }
+ last = c;
+ }
+ }
+ c = last;
+ } while (c >= 0);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+
+static void ILLfactor_ftranu3 (
+ EGLPNUM_TYPENAME_factor_work * f,
+ EGLPNUM_TYPENAME_svector * a,
+ EGLPNUM_TYPENAME_svector * x)
+{
+ EGLPNUM_TYPE *work = f->work_coef;
+ int anzcnt = a->nzcnt;
+ int *aindx = a->indx;
+ EGLPNUM_TYPE *acoef = a->coef;
+ EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+ int i;
+
+ for (i = 0; i < anzcnt; i++)
+ {
+ if (uc_inf[aindx[i]].delay++ == 0)
+ {
+ ftranu3_delay2 (f, aindx[i]);
+ }
+ EGLPNUM_TYPENAME_EGlpNumCopy (work[aindx[i]], acoef[i]);
+ }
+ x->nzcnt = 0;
+ for (i = 0; i < anzcnt; i++)
+ {
+ if (--uc_inf[aindx[i]].delay == 0)
+ {
+ ftranu3_process2 (f, aindx[i], x);
+ }
+ }
+#ifdef SOLVE_DEBUG
+ QSlog("EGLPNUM_TYPENAME_ILLfactor_ftran x after u3:");
+ for (i = 0; i < x->nzcnt; i++)
+ {
+ QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (x->coef[i]), x->indx[i]);
+ }
+#endif /* SOLVE_DEBUG */
+}
+
+/* EGLPNUM_TYPENAME_ILLfactor_ftran solves Bx=a for x */
+void EGLPNUM_TYPENAME_ILLfactor_ftran (
+ EGLPNUM_TYPENAME_factor_work * f,
+ EGLPNUM_TYPENAME_svector * a,
+ EGLPNUM_TYPENAME_svector * x)
+{
+ int i;
+ int nzcnt;
+ int sparse;
+ int *aindx;
+ EGLPNUM_TYPE *acoef;
+ EGLPNUM_TYPE *work_coef = f->work_coef;
+
+#ifdef RECORD
+ {
+ EGioPrintf (fsave, "f %d", a->nzcnt);
+ for (i = 0; i < a->nzcnt; i++)
+ {
+ EGioPrintf (fsave, " %d %.16e", a->indx[i], EGLPNUM_TYPENAME_EGlpNumToLf (a->coef[i]));
+ }
+ EGioPrintf (fsave, "\n");
+ EGioFlush (fsave);
+ }
+#endif /* RECORD */
+#ifdef DEBUG_FACTOR
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLfactor_ftran a:");
+ for (i = 0; i < a->nzcnt; i++)
+ {
+ QSlog(" %d %la", a->indx[i], EGLPNUM_TYPENAME_EGlpNumToLf (a->coef[i]));
+ }
+ }
+#endif /* DEBUG_FACTOR */
+
+ if (a->nzcnt >= SPARSE_FACTOR * f->dim)
+ {
+ nzcnt = a->nzcnt;
+ aindx = a->indx;
+ acoef = a->coef;
+ for (i = 0; i < nzcnt; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
+ }
+ sparse = 0;
+ }
+ else
+ {
+ sparse = 1;
+ }
+
+ if (sparse)
+ {
+ ILLfactor_ftranl3 (f, a, &f->xtmp);
+ if (f->xtmp.nzcnt >= SPARSE_FACTOR * f->dim)
+ {
+ nzcnt = f->xtmp.nzcnt;
+ aindx = f->xtmp.indx;
+ acoef = f->xtmp.coef;
+
+ for (i = 0; i < nzcnt; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
+ }
+ sparse = 0;
+ }
+ }
+ else
+ {
+ ILLfactor_ftranl (f, work_coef);
+ }
+
+ if (sparse)
+ {
+ ILLfactor_ftrane2 (f, &f->xtmp);
+ if (f->xtmp.nzcnt >= SPARSE_FACTOR * f->dim)
+ {
+ nzcnt = f->xtmp.nzcnt;
+ aindx = f->xtmp.indx;
+ acoef = f->xtmp.coef;
+
+ for (i = 0; i < nzcnt; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
+ }
+ sparse = 0;
+ }
+ }
+ else
+ {
+ ILLfactor_ftrane (f, work_coef);
+ }
+
+ if (sparse)
+ {
+ ILLfactor_ftranu3 (f, &f->xtmp, x);
+ }
+ else
+ {
+ ILLfactor_ftranu (f, work_coef, x);
+ }
+
+#ifdef SORT_RESULTS
+ sort_vector (x);
+#endif
+
+#ifdef DEBUG_FACTOR
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLfactor_ftran x:");
+ for (i = 0; i < x->nzcnt; i++)
+ {
+ QSlog(" %d %la", x->indx[i], EGLPNUM_TYPENAME_EGlpNumToLf (x->coef[i]));
+ }
+ }
+#endif /* DEBUG_FACTOR */
+ return;
+}
+
+/* EGLPNUM_TYPENAME_ILLfactor_ftran_update solves Bx=a for x, and also returns upd, where Ux=upd */
+void EGLPNUM_TYPENAME_ILLfactor_ftran_update (
+ EGLPNUM_TYPENAME_factor_work * f,
+ EGLPNUM_TYPENAME_svector * a,
+ EGLPNUM_TYPENAME_svector * upd,
+ EGLPNUM_TYPENAME_svector * x)
+{
+ int i;
+ int nzcnt;
+ int dim;
+ int sparse;
+ int *aindx;
+ EGLPNUM_TYPE *acoef;
+ EGLPNUM_TYPE *work_coef = f->work_coef;
+
+#ifdef RECORD
+ {
+ EGioPrintf (fsave, "F %d", a->nzcnt);
+ for (i = 0; i < a->nzcnt; i++)
+ {
+ EGioPrintf (fsave, " %d %.16e", a->indx[i], EGLPNUM_TYPENAME_EGlpNumToLf (a->coef[i]));
+ }
+ EGioPrintf (fsave, "\n");
+ EGioFlush (fsave);
+ }
+#endif /* RECORD */
+#ifdef DEBUG_FACTOR
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLfactor_ftran_update a:");
+ for (i = 0; i < a->nzcnt; i++)
+ {
+ QSlog(" %d %.3f", a->indx[i], EGLPNUM_TYPENAME_EGlpNumToLf (a->coef[i]));
+ }
+ }
+#endif /* DEBUG_FACTOR */
+
+ if (a->nzcnt >= SPARSE_FACTOR * f->dim)
+ {
+ aindx = a->indx;
+ acoef = a->coef;
+ nzcnt = a->nzcnt;
+
+ for (i = 0; i < nzcnt; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
+ }
+ sparse = 0;
+ }
+ else
+ {
+ sparse = 1;
+ }
+
+ if (sparse)
+ {
+ ILLfactor_ftranl3 (f, a, upd);
+ if (upd->nzcnt >= SPARSE_FACTOR * f->dim)
+ {
+ nzcnt = upd->nzcnt;
+ aindx = upd->indx;
+ acoef = upd->coef;
+
+ for (i = 0; i < nzcnt; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
+ }
+ sparse = 0;
+ }
+ }
+ else
+ {
+ ILLfactor_ftranl (f, work_coef);
+ }
+
+ if (sparse)
+ {
+ ILLfactor_ftrane2 (f, upd);
+ if (upd->nzcnt >= SPARSE_FACTOR * f->dim)
+ {
+ nzcnt = upd->nzcnt;
+ aindx = upd->indx;
+ acoef = upd->coef;
+
+ for (i = 0; i < nzcnt; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
+ }
+ sparse = 0;
+ }
+ }
+ else
+ {
+ ILLfactor_ftrane (f, work_coef);
+ nzcnt = 0;
+ dim = f->dim;
+ aindx = upd->indx;
+ acoef = upd->coef;
+ for (i = 0; i < dim; i++)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (work_coef[i]))
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (work_coef[i], f->szero_tol))
+ /*if(work_coef[i] > szero_tol || work_coef[i] < -szero_tol) */
+ {
+ aindx[nzcnt] = i;
+ EGLPNUM_TYPENAME_EGlpNumCopy (acoef[nzcnt], work_coef[i]);
+ nzcnt++;
+ }
+ }
+ }
+ upd->nzcnt = nzcnt;
+ }
+
+ if (sparse)
+ {
+ ILLfactor_ftranu3 (f, upd, x);
+ }
+ else
+ {
+ ILLfactor_ftranu (f, work_coef, x);
+ }
+
+#ifdef SORT_RESULTS
+ sort_vector (upd);
+ sort_vector (x);
+#endif
+
+#ifdef DEBUG_FACTOR
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLfactor_ftran update x:");
+ for (i = 0; i < x->nzcnt; i++)
+ {
+ QSlog(" %d %.3f", x->indx[i], EGLPNUM_TYPENAME_EGlpNumToLf (x->coef[i]));
+ }
+ }
+#endif /* DEBUG_FACTOR */
+}
+
+
+static void ILLfactor_btranl2 (
+ EGLPNUM_TYPENAME_factor_work * f,
+ EGLPNUM_TYPE * x)
+{
+ int *lrindx = f->lrindx;
+ EGLPNUM_TYPE *lrcoef = f->lrcoef;
+ EGLPNUM_TYPENAME_lr_info *lr_inf = f->lr_inf;
+ int dim = f->dim;
+ int nzcnt;
+ int beg;
+ int i;
+ int j;
+ EGLPNUM_TYPE v;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+ for (i = dim - 1; i >= 0; i--)
+ {
+#ifdef SOLVE_DEBUG
+#if (SOLVE_DEBUG+0 > 1)
+ QSlog("EGLPNUM_TYPENAME_ILLfactor_btran x before l2 %d:", i);
+ for (j = 0; j < f->dim; j++)
+ {
+ QSlog(" %.3f", EGLPNUM_TYPENAME_EGlpNumToLf (x[j]));
+ }
+#endif
+#endif /* SOLVE_DEBUG */
+ EGLPNUM_TYPENAME_EGlpNumCopy (v, x[lr_inf[i].r]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (v))
+ {
+ nzcnt = lr_inf[i].nzcnt;
+ beg = lr_inf[i].rbeg;
+ for (j = 0; j < nzcnt; j++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (x[lrindx[beg + j]], v, lrcoef[beg + j]);
+ }
+ }
+ }
+#ifdef SOLVE_DEBUG
+#if (SOLVE_DEBUG+0 <= 1)
+ QSlog("EGLPNUM_TYPENAME_ILLfactor_btran x after l2:");
+ for (j = 0; j < f->dim; j++)
+ {
+ QSlog(" %.3f", EGLPNUM_TYPENAME_EGlpNumToLf (x[j]));
+ }
+#endif
+#endif /* SOLVE_DEBUG */
+ EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+
+#if 0
+static void btranl3_delay (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int r)
+{
+ EGLPNUM_TYPENAME_lr_info *lr_inf = f->lr_inf;
+ int nzcnt;
+ int *indx;
+ int i;
+
+ r = lr_inf[r].rrank;
+ nzcnt = lr_inf[r].nzcnt;
+ indx = f->lrindx + lr_inf[r].rbeg;
+ for (i = 0; i < nzcnt; i++)
+ {
+ r = indx[i];
+ if (lr_inf[r].delay++ == 0)
+ {
+ btranl3_delay (f, r);
+ }
+ }
+}
+#endif
+
+static void btranl3_delay2 (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int r)
+{
+ EGLPNUM_TYPENAME_lr_info *lr_inf = f->lr_inf;
+ int nzcnt;
+ int *indx;
+ int i;
+ int last;
+
+ do
+ {
+ r = lr_inf[r].rrank;
+ nzcnt = lr_inf[r].nzcnt;
+ indx = f->lrindx + lr_inf[r].rbeg;
+ last = -1;
+ for (i = 0; i < nzcnt; i++)
+ {
+ r = indx[i];
+ if (lr_inf[r].delay++ == 0)
+ {
+ if (last >= 0)
+ {
+ btranl3_delay2 (f, last);
+ }
+ last = r;
+ }
+ }
+ r = last;
+ } while (r >= 0);
+}
+
+#if 0
+static void btranl3_process (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int r,
+ EGLPNUM_TYPENAME_svector * x)
+{
+ EGLPNUM_TYPENAME_lr_info *lr_inf = f->lr_inf;
+ EGLPNUM_TYPE *work = f->work_coef;
+ int nzcnt;
+ int *indx;
+ EGLPNUM_TYPE *coef;
+ int i;
+ EGLPNUM_TYPE v;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (v, work[r]);
+ EGLPNUM_TYPENAME_EGlpNumZero (work[r]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (v, f->szero_tol))
+ /*if (v > szero_tol || v < -szero_tol) */
+ {
+ x->indx[x->nzcnt] = r;
+ EGLPNUM_TYPENAME_EGlpNumCopy (x->coef[x->nzcnt], v);
+ x->nzcnt++;
+ }
+ r = lr_inf[r].rrank;
+ nzcnt = lr_inf[r].nzcnt;
+ indx = f->lrindx + lr_inf[r].rbeg;
+ coef = f->lrcoef + lr_inf[r].rbeg;
+ for (i = 0; i < nzcnt; i++)
+ {
+ r = indx[i];
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (work[r], v, coef[i]);
+ if (--lr_inf[r].delay == 0)
+ {
+ btranl3_process (f, r, x);
+ }
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+#endif
+
+static void btranl3_process2 (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int r,
+ EGLPNUM_TYPENAME_svector * x)
+{
+ EGLPNUM_TYPENAME_lr_info *lr_inf = f->lr_inf;
+ EGLPNUM_TYPE *work = f->work_coef;
+ int nzcnt;
+ int *indx;
+ EGLPNUM_TYPE *coef;
+ int i;
+ int last;
+ EGLPNUM_TYPE v;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+ do
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (v, work[r]);
+ EGLPNUM_TYPENAME_EGlpNumZero (work[r]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (v, f->szero_tol))
+ /*if (v > szero_tol || v < -szero_tol) */
+ {
+ x->indx[x->nzcnt] = r;
+ EGLPNUM_TYPENAME_EGlpNumCopy (x->coef[x->nzcnt], v);
+ x->nzcnt++;
+ }
+ r = lr_inf[r].rrank;
+ nzcnt = lr_inf[r].nzcnt;
+ indx = f->lrindx + lr_inf[r].rbeg;
+ coef = f->lrcoef + lr_inf[r].rbeg;
+ last = -1;
+ for (i = 0; i < nzcnt; i++)
+ {
+ r = indx[i];
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (work[r], v, coef[i]);
+ if (--lr_inf[r].delay == 0)
+ {
+ if (last >= 0)
+ {
+ btranl3_process2 (f, last, x);
+ }
+ last = r;
+ }
+ }
+ r = last;
+ } while (r >= 0);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+
+static void ILLfactor_btranl3 (
+ EGLPNUM_TYPENAME_factor_work * f,
+ EGLPNUM_TYPENAME_svector * a,
+ EGLPNUM_TYPENAME_svector * x)
+{
+ EGLPNUM_TYPE *work = f->work_coef;
+ int anzcnt = a->nzcnt;
+ int *aindx = a->indx;
+ EGLPNUM_TYPE *acoef = a->coef;
+ EGLPNUM_TYPENAME_lr_info *lr_inf = f->lr_inf;
+ int i;
+
+ for (i = 0; i < anzcnt; i++)
+ {
+ if (lr_inf[aindx[i]].delay++ == 0)
+ {
+ btranl3_delay2 (f, aindx[i]);
+ }
+ EGLPNUM_TYPENAME_EGlpNumCopy (work[aindx[i]], acoef[i]);
+ }
+ x->nzcnt = 0;
+ for (i = 0; i < anzcnt; i++)
+ {
+ if (--lr_inf[aindx[i]].delay == 0)
+ {
+ btranl3_process2 (f, aindx[i], x);
+ }
+ }
+#ifdef SOLVE_DEBUG
+ QSlog("EGLPNUM_TYPENAME_ILLfactor_btran x after l3:");
+ for (i = 0; i < x->nzcnt; i++)
+ {
+ QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (x->coef[i]), x->indx[i]);
+ }
+#endif /* SOLVE_DEBUG */
+}
+
+static void ILLfactor_btrane (
+ EGLPNUM_TYPENAME_factor_work * f,
+ EGLPNUM_TYPE * x)
+{
+ int *erindx = f->erindx;
+ EGLPNUM_TYPE *ercoef = f->ercoef;
+ EGLPNUM_TYPENAME_er_info *er_inf = f->er_inf;
+ int etacnt = f->etacnt;
+ int beg;
+ int nzcnt;
+ int i;
+ int j;
+ EGLPNUM_TYPE v;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+ for (i = etacnt - 1; i >= 0; i--)
+ {
+#ifdef SOLVE_DEBUG
+#if (SOLVE_DEBUG+0 > 1)
+ QSlog("EGLPNUM_TYPENAME_ILLfactor_btran x before eta %d:", i);
+ for (j = 0; j < f->dim; j++)
+ {
+ QSlog(" %.3f", EGLPNUM_TYPENAME_EGlpNumToLf (x[j]));
+ }
+#endif
+#endif /* SOLVE_DEBUG */
+ EGLPNUM_TYPENAME_EGlpNumCopy (v, x[er_inf[i].r]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (v))
+ {
+ nzcnt = er_inf[i].nzcnt;
+ beg = er_inf[i].rbeg;
+ for (j = 0; j < nzcnt; j++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (x[erindx[beg + j]], v, ercoef[beg + j]);
+ }
+ }
+ }
+#ifdef SOLVE_DEBUG
+#if (SOLVE_DEBUG+0 <= 1)
+ QSlog("EGLPNUM_TYPENAME_ILLfactor_btran x after eta:");
+ for (j = 0; j < f->dim; j++)
+ {
+ QSlog(" %.3f", EGLPNUM_TYPENAME_EGlpNumToLf (x[j]));
+ }
+#endif
+#endif /* SOLVE_DEBUG */
+ EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+
+static void ILLfactor_btrane2 (
+ EGLPNUM_TYPENAME_factor_work * f,
+ EGLPNUM_TYPENAME_svector * x)
+{
+ int *erindx = f->erindx;
+ EGLPNUM_TYPE *ercoef = f->ercoef;
+ EGLPNUM_TYPENAME_er_info *er_inf = f->er_inf;
+ int etacnt = f->etacnt;
+ int beg;
+ int nzcnt;
+ int xnzcnt = x->nzcnt;
+ int *xindx = x->indx;
+ EGLPNUM_TYPE *xcoef = x->coef;
+ EGLPNUM_TYPE *work_coef = f->work_coef;
+ int *work_indx = f->work_indx;
+ int i;
+ int j;
+ EGLPNUM_TYPE v;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+ for (i = 0; i < xnzcnt; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (work_coef[xindx[i]], xcoef[i]);
+ work_indx[xindx[i]] = i + 1;
+ }
+ for (i = etacnt - 1; i >= 0; i--)
+ {
+#ifdef SOLVE_DEBUG
+#if (SOLVE_DEBUG+0 > 1)
+ QSlog("EGLPNUM_TYPENAME_ILLfactor_btran x before eta2 %d:", i);
+ for (j = 0; j < xnzcnt; j++)
+ {
+ QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (work_coef[xindx[j]]), xindx[j]);
+ }
+#endif
+#endif /* SOLVE_DEBUG */
+ EGLPNUM_TYPENAME_EGlpNumCopy (v, work_coef[er_inf[i].r]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (v))
+ {
+ nzcnt = er_inf[i].nzcnt;
+ beg = er_inf[i].rbeg;
+ for (j = 0; j < nzcnt; j++)
+ {
+ if (work_indx[erindx[beg + j]] == 0)
+ {
+ work_indx[erindx[beg + j]] = xnzcnt;
+ xindx[xnzcnt++] = erindx[beg + j];
+ }
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (work_coef[erindx[beg + j]], v, ercoef[beg + j]);
+ }
+ }
+ }
+
+ j = 0;
+ while (j < xnzcnt)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (xcoef[j], work_coef[xindx[j]]);
+ EGLPNUM_TYPENAME_EGlpNumZero (work_coef[xindx[j]]);
+ work_indx[xindx[j]] = 0;
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (xcoef[j]))
+ {
+ --xnzcnt;
+ xindx[j] = xindx[xnzcnt];
+ }
+ else
+ {
+ j++;
+ }
+ }
+ x->nzcnt = xnzcnt;
+
+#ifdef SOLVE_DEBUG
+#if (SOLVE_DEBUG+0 <= 1)
+ QSlog("EGLPNUM_TYPENAME_ILLfactor_btran x after eta2:");
+ for (j = 0; j < xnzcnt; j++)
+ {
+ QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (xcoef[j]), xindx[j]);
+ }
+#endif
+#endif /* SOLVE_DEBUG */
+ EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+
+static void ILLfactor_btranu (
+ EGLPNUM_TYPENAME_factor_work * f,
+ EGLPNUM_TYPE * a,
+ EGLPNUM_TYPENAME_svector * x)
+{
+ int *urindx = f->urindx;
+ EGLPNUM_TYPE *urcoef = f->urcoef;
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+ int *rperm = f->rperm;
+ int *cperm = f->cperm;
+ int dim = f->dim;
+ int xnzcnt = 0;
+ int *xindx = x->indx;
+ EGLPNUM_TYPE *xcoef = x->coef;
+ int nzcnt;
+ int beg;
+ int i;
+ int j;
+ EGLPNUM_TYPE v;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+ for (i = 0; i < dim; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (v, a[cperm[i]]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (v))
+ {
+ j = rperm[i];
+ beg = ur_inf[j].rbeg;
+ EGLPNUM_TYPENAME_EGlpNumDivTo (v, urcoef[beg]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (v, f->szero_tol)) /*
+ * if (v > szero_tol || v < -szero_tol) */
+ {
+ xindx[xnzcnt] = j;
+ EGLPNUM_TYPENAME_EGlpNumCopy (xcoef[xnzcnt], v);
+ xnzcnt++;
+ }
+ nzcnt = ur_inf[j].nzcnt;
+ for (j = 1; j < nzcnt; j++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (a[urindx[beg + j]], v, urcoef[beg + j]);
+ }
+ EGLPNUM_TYPENAME_EGlpNumZero (a[cperm[i]]);
+ }
+ }
+ x->nzcnt = xnzcnt;
+#ifdef SOLVE_DEBUG
+ QSlog("EGLPNUM_TYPENAME_ILLfactor_btran x after u:");
+ for (i = 0; i < x->nzcnt; i++)
+ {
+ QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (x->coef[i]), x->indx[i]);
+ }
+#endif /* SOLVE_DEBUG */
+ EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+
+
+#if 0
+static void btranu3_delay (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int r)
+{
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+ int nzcnt;
+ int *indx;
+ int i;
+
+ r = f->rperm[f->crank[r]];
+ nzcnt = ur_inf[r].nzcnt;
+ indx = f->urindx + ur_inf[r].rbeg;
+ for (i = 1; i < nzcnt; i++)
+ {
+ r = indx[i];
+ if (ur_inf[r].delay++ == 0)
+ {
+ btranu3_delay (f, r);
+ }
+ }
+}
+#endif
+
+static void btranu3_delay2 (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int r)
+{
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+ int nzcnt;
+ int *indx;
+ int i;
+ int last;
+
+ do
+ {
+ r = f->rperm[f->crank[r]];
+ nzcnt = ur_inf[r].nzcnt;
+ indx = f->urindx + ur_inf[r].rbeg;
+ last = -1;
+ for (i = 1; i < nzcnt; i++)
+ {
+ r = indx[i];
+ if (ur_inf[r].delay++ == 0)
+ {
+ if (last >= 0)
+ {
+ btranu3_delay2 (f, last);
+ }
+ last = r;
+ }
+ }
+ r = last;
+ } while (r >= 0);
+}
+
+#if 0
+static void btranu3_process (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int r,
+ EGLPNUM_TYPENAME_svector * x)
+{
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+ EGLPNUM_TYPE *work = f->work_coef;
+ int nzcnt;
+ int *indx;
+ EGLPNUM_TYPE *coef;
+ int i;
+ EGLPNUM_TYPE v;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (v, work[r]);
+ EGLPNUM_TYPENAME_EGlpNumZero (work[r]);
+ r = f->rperm[f->crank[r]];
+ nzcnt = ur_inf[r].nzcnt;
+ indx = f->urindx + ur_inf[r].rbeg;
+ coef = f->urcoef + ur_inf[r].rbeg;
+ EGLPNUM_TYPENAME_EGlpNumDivTo (v, coef[0]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (v))
+ {
+ x->indx[x->nzcnt] = r;
+ EGLPNUM_TYPENAME_EGlpNumCopy (x->coef[x->nzcnt], v);
+ x->nzcnt++;
+ }
+ for (i = 1; i < nzcnt; i++)
+ {
+ r = indx[i];
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (work[r], v, coef[i]);
+ if (--ur_inf[r].delay == 0)
+ {
+ btranu3_process (f, r, x);
+ }
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+#endif
+
+static void btranu3_process2 (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int r,
+ EGLPNUM_TYPENAME_svector * x)
+{
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+ EGLPNUM_TYPE *work = f->work_coef;
+ int nzcnt;
+ int *indx;
+ EGLPNUM_TYPE *coef;
+ int i;
+ int last;
+ EGLPNUM_TYPE v;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+ do
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (v, work[r]);
+ EGLPNUM_TYPENAME_EGlpNumZero (work[r]);
+ r = f->rperm[f->crank[r]];
+ nzcnt = ur_inf[r].nzcnt;
+ indx = f->urindx + ur_inf[r].rbeg;
+ coef = f->urcoef + ur_inf[r].rbeg;
+ EGLPNUM_TYPENAME_EGlpNumDivTo (v, coef[0]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (v))
+ {
+ x->indx[x->nzcnt] = r;
+ EGLPNUM_TYPENAME_EGlpNumCopy (x->coef[x->nzcnt], v);
+ x->nzcnt++;
+ }
+ last = -1;
+ for (i = 1; i < nzcnt; i++)
+ {
+ r = indx[i];
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (work[r], v, coef[i]);
+ if (--ur_inf[r].delay == 0)
+ {
+ if (last >= 0)
+ {
+ btranu3_process2 (f, last, x);
+ }
+ last = r;
+ }
+ }
+ r = last;
+ } while (r >= 0);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+}
+
+static void ILLfactor_btranu3 (
+ EGLPNUM_TYPENAME_factor_work * f,
+ EGLPNUM_TYPENAME_svector * a,
+ EGLPNUM_TYPENAME_svector * x)
+{
+ EGLPNUM_TYPE *work = f->work_coef;
+ int anzcnt = a->nzcnt;
+ int *aindx = a->indx;
+ EGLPNUM_TYPE *acoef = a->coef;
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+ int i;
+
+ for (i = 0; i < anzcnt; i++)
+ {
+ if (ur_inf[aindx[i]].delay++ == 0)
+ {
+ btranu3_delay2 (f, aindx[i]);
+ }
+ EGLPNUM_TYPENAME_EGlpNumCopy (work[aindx[i]], acoef[i]);
+ }
+ x->nzcnt = 0;
+ for (i = 0; i < anzcnt; i++)
+ {
+ if (--ur_inf[aindx[i]].delay == 0)
+ {
+ btranu3_process2 (f, aindx[i], x);
+ }
+ }
+#ifdef SOLVE_DEBUG
+ QSlog("EGLPNUM_TYPENAME_ILLfactor_btran x after u3:");
+ for (i = 0; i < x->nzcnt; i++)
+ {
+ QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (x->coef[i]), x->indx[i]);
+ }
+#endif /* SOLVE_DEBUG */
+}
+
+/* EGLPNUM_TYPENAME_ILLfactor_btran solves x^tB=a^t (or, B^t x = a) for x */
+void EGLPNUM_TYPENAME_ILLfactor_btran (
+ EGLPNUM_TYPENAME_factor_work * f,
+ EGLPNUM_TYPENAME_svector * a,
+ EGLPNUM_TYPENAME_svector * x)
+{
+ int i;
+ int nzcnt;
+ int sparse;
+ int *aindx = a->indx;
+ EGLPNUM_TYPE *acoef = a->coef;
+ EGLPNUM_TYPE *work_coef = f->work_coef;
+ int dim = f->dim;
+
+#ifdef RECORD
+ {
+ EGioPrintf (fsave, "b %d", a->nzcnt);
+ for (i = 0; i < a->nzcnt; i++)
+ {
+ EGioPrintf (fsave, " %d %.16e", a->indx[i], EGLPNUM_TYPENAME_EGlpNumToLf (a->coef[i]));
+ }
+ EGioPrintf (fsave, "\n");
+ EGioFlush (fsave);
+ }
+#endif /* RECORD */
+#ifdef DEBUG_FACTOR
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLfactor_btran a:");
+ for (i = 0; i < a->nzcnt; i++)
+ {
+ QSlog(" %d %.3f", a->indx[i], EGLPNUM_TYPENAME_EGlpNumToLf (a->coef[i]));
+ }
+ }
+#endif /* DEBUG_FACTOR */
+
+ if (a->nzcnt >= SPARSE_FACTOR * f->dim)
+ {
+ aindx = a->indx;
+ acoef = a->coef;
+ work_coef = f->work_coef;
+ nzcnt = a->nzcnt;
+ for (i = 0; i < nzcnt; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
+ }
+ sparse = 0;
+ }
+ else
+ {
+ sparse = 1;
+ }
+
+ if (sparse)
+ {
+ ILLfactor_btranu3 (f, a, &f->xtmp);
+ }
+ else
+ {
+ ILLfactor_btranu (f, work_coef, &f->xtmp);
+ }
+
+ if (f->xtmp.nzcnt >= SPARSE_FACTOR * f->dim)
+ {
+ aindx = f->xtmp.indx;
+ acoef = f->xtmp.coef;
+ work_coef = f->work_coef;
+ nzcnt = f->xtmp.nzcnt;
+ for (i = 0; i < nzcnt; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
+ }
+ sparse = 0;
+ }
+ else
+ {
+ sparse = 1;
+ }
+
+ if (sparse)
+ {
+ ILLfactor_btrane2 (f, &f->xtmp);
+ if (f->xtmp.nzcnt >= SPARSE_FACTOR * f->dim)
+ {
+ aindx = f->xtmp.indx;
+ acoef = f->xtmp.coef;
+ work_coef = f->work_coef;
+ nzcnt = f->xtmp.nzcnt;
+ for (i = 0; i < nzcnt; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
+ }
+ sparse = 0;
+ }
+ }
+ else
+ {
+ ILLfactor_btrane (f, work_coef);
+ }
+
+ if (sparse)
+ {
+ ILLfactor_btranl3 (f, &f->xtmp, x);
+ }
+ else
+ {
+ ILLfactor_btranl2 (f, work_coef);
+ dim = f->dim;
+ nzcnt = 0;
+ aindx = x->indx;
+ acoef = x->coef;
+ for (i = 0; i < dim; i++)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (work_coef[i]))
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (work_coef[i], f->szero_tol))
+ /*if (work_coef[i] > szero_tol || work_coef[i] < -szero_tol) */
+ {
+ aindx[nzcnt] = i;
+ EGLPNUM_TYPENAME_EGlpNumCopy (acoef[nzcnt], work_coef[i]);
+ nzcnt++;
+ }
+ EGLPNUM_TYPENAME_EGlpNumZero (work_coef[i]);
+ }
+ }
+ x->nzcnt = nzcnt;
+ }
+
+#ifdef SORT_RESULTS
+ sort_vector (x);
+#endif
+
+#ifdef DEBUG_FACTOR
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLfactor_btran x:");
+ for (i = 0; i < x->nzcnt; i++)
+ {
+ QSlog(" %d %.3f", x->indx[i], EGLPNUM_TYPENAME_EGlpNumToLf (x->coef[i]));
+ }
+ }
+#endif /* DEBUG_FACTOR */
+ return;
+}
+
+static int expand_col (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int col)
+{
+ EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf + col;
+ int uc_freebeg = f->uc_freebeg;
+ int nzcnt = uc_inf->nzcnt;
+ int cbeg;
+ EGLPNUM_TYPE *uccoef;
+ int *ucindx;
+ int *ucrind;
+ int i;
+ int rval = 0;
+
+ if (uc_freebeg + nzcnt + 1 >= f->uc_space)
+ {
+ rval = make_uc_space (f, nzcnt + 1);
+ CHECKRVALG (rval, CLEANUP);
+ uc_freebeg = f->uc_freebeg;
+ }
+ cbeg = uc_inf->cbeg;
+ uccoef = f->uccoef;
+ ucindx = f->ucindx;
+ ucrind = f->ucrind;
+
+ for (i = 0; i < nzcnt; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (uccoef[uc_freebeg + i], uccoef[cbeg + i]);
+ ucindx[uc_freebeg + i] = ucindx[cbeg + i];
+ ucrind[uc_freebeg + i] = ucrind[cbeg + i];
+ ucindx[cbeg + i] = -1;
+ }
+
+ uc_inf->cbeg = uc_freebeg;
+ f->uc_freebeg = uc_freebeg + nzcnt;
+CLEANUP:
+ EG_RETURN (rval);
+}
+
+static int expand_row (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int row)
+{
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf + row;
+ int ur_freebeg = f->ur_freebeg;
+ int nzcnt = ur_inf->nzcnt;
+ int rbeg;
+ EGLPNUM_TYPE *urcoef;
+ int *urindx;
+ int *urcind;
+ int i;
+ int rval = 0;
+
+ if (ur_freebeg + nzcnt + 1 >= f->ur_space)
+ {
+ rval = make_ur_space (f, nzcnt + 1);
+ CHECKRVALG (rval, CLEANUP);
+ ur_freebeg = f->ur_freebeg;
+ }
+ rbeg = ur_inf->rbeg;
+ urcoef = f->urcoef;
+ urindx = f->urindx;
+ urcind = f->urcind;
+
+ for (i = 0; i < nzcnt; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (urcoef[ur_freebeg + i], urcoef[rbeg + i]);
+ urindx[ur_freebeg + i] = urindx[rbeg + i];
+ urcind[ur_freebeg + i] = urcind[rbeg + i];
+ urindx[rbeg + i] = -1;
+ }
+
+ ur_inf->rbeg = ur_freebeg;
+ f->ur_freebeg = ur_freebeg + nzcnt;
+CLEANUP:
+ EG_RETURN (rval);
+}
+
+static int add_nonzero (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int row,
+ int col,
+ EGLPNUM_TYPE val)
+{
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf + row;
+ EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf + col;
+ int cnzcnt = uc_inf->nzcnt;
+ int rnzcnt = ur_inf->nzcnt;
+ int cloc = uc_inf->cbeg + cnzcnt;
+ int rloc = ur_inf->rbeg + rnzcnt;
+ int rval = 0;
+
+ if (f->ucindx[cloc] != -1)
+ {
+ rval = expand_col (f, col);
+ CHECKRVALG (rval, CLEANUP);
+ cloc = uc_inf->cbeg + cnzcnt;
+ }
+ TESTG ((rval = (rloc < 0 || rloc > f->ur_space)), CLEANUP,
+ "rloc %d outside boundaries [0:%d]", rloc, f->ur_space);
+ if (f->urindx[rloc] != -1)
+ {
+ rval = expand_row (f, row);
+ CHECKRVALG (rval, CLEANUP);
+ rloc = ur_inf->rbeg + rnzcnt;
+ }
+ f->ucindx[cloc] = row;
+ EGLPNUM_TYPENAME_EGlpNumCopy (f->uccoef[cloc], val);
+ f->ucrind[cloc] = rnzcnt;
+ f->urindx[rloc] = col;
+ EGLPNUM_TYPENAME_EGlpNumCopy (f->urcoef[rloc], val);
+ f->urcind[rloc] = cnzcnt;
+
+ if (cloc == f->uc_freebeg)
+ f->uc_freebeg++;
+ if (rloc == f->ur_freebeg)
+ f->ur_freebeg++;
+
+ uc_inf->nzcnt = cnzcnt + 1;
+ ur_inf->nzcnt = rnzcnt + 1;
+CLEANUP:
+ EG_RETURN (rval);
+}
+
+static int delete_nonzero_row (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int row,
+ int ind)
+{
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+ EGLPNUM_TYPE *urcoef = f->urcoef;
+ int *urindx = f->urindx;
+ int *urcind = f->urcind;
+ int *ucrind = f->ucrind;
+ int rbeg = ur_inf[row].rbeg;
+ int nzcnt = ur_inf[row].nzcnt - 1;
+ int cbeg, rval = 0;
+ #ifdef DEBUG_FACTOR
+ TESTG((rval=(nzcnt<0)),CLEANUP,"Deleting empty row %d ind %d!",row, ind);
+ #endif
+
+ if (ind != nzcnt)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (urcoef[rbeg + ind], urcoef[rbeg + nzcnt]);
+ urindx[rbeg + ind] = urindx[rbeg + nzcnt];
+ urcind[rbeg + ind] = urcind[rbeg + nzcnt];
+ cbeg = f->uc_inf[urindx[rbeg + nzcnt]].cbeg;
+ ucrind[cbeg + urcind[rbeg + nzcnt]] = ind;
+ urindx[rbeg + nzcnt] = -1;
+ }
+ ur_inf[row].nzcnt = nzcnt;
+ #ifdef DEBUG_FACTOR
+ CLEANUP:
+ #endif
+ return rval;
+}
+
+static void delete_nonzero_col (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int col,
+ int ind)
+{
+ EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+ EGLPNUM_TYPE *uccoef = f->uccoef;
+ int *ucindx = f->ucindx;
+ int *ucrind = f->ucrind;
+ int *urcind = f->urcind;
+ int cbeg = uc_inf[col].cbeg;
+ int nzcnt = uc_inf[col].nzcnt - 1;
+ int rbeg;
+
+ if (ind != nzcnt)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (uccoef[cbeg + ind], uccoef[cbeg + nzcnt]);
+ ucindx[cbeg + ind] = ucindx[cbeg + nzcnt];
+ ucrind[cbeg + ind] = ucrind[cbeg + nzcnt];
+ rbeg = f->ur_inf[ucindx[cbeg + nzcnt]].rbeg;
+ urcind[rbeg + ucrind[cbeg + nzcnt]] = ind;
+ ucindx[cbeg + nzcnt] = -1;
+ }
+ uc_inf[col].nzcnt = nzcnt;
+}
+
+static int delete_column (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int col)
+{
+ EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+ int beg = uc_inf[col].cbeg;
+ int nzcnt = uc_inf[col].nzcnt;
+ int *ucindx = f->ucindx + beg;
+ int *ucrind = f->ucrind + beg;
+ int i, rval = 0;
+ #ifdef DEBUG_FACTOR
+ rval = check_matrix(f);
+ TESTG(rval,CLEANUP,"Corrupted Matrix");
+ #endif
+
+ for (i = 0; i < nzcnt; i++)
+ {
+ rval = delete_nonzero_row (f, ucindx[i], ucrind[i]);
+ CHECKRVALG(rval,CLEANUP);
+ ucindx[i] = -1;
+ }
+ uc_inf[col].nzcnt = 0;
+
+#ifdef TRACK_FACTOR
+ f->nzcnt_cur -= nzcnt;
+#endif
+
+ #ifdef DEBUG_FACTOR
+ rval = check_matrix(f);
+ TESTG(rval,CLEANUP,"Corrupted Matrix");
+ #endif /* DEBUG_FACTOR */
+ CLEANUP:
+ EG_RETURN(rval);
+}
+
+static int delete_row (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int row,
+ EGLPNUM_TYPENAME_svector * x)
+{
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+ int beg = ur_inf[row].rbeg;
+ int nzcnt = ur_inf[row].nzcnt;
+ int *urindx = f->urindx + beg;
+ EGLPNUM_TYPE *urcoef = f->urcoef + beg;
+ int *urcind = f->urcind + beg;
+ int i,rval=0;
+
+ #ifdef DEBUG_FACTOR
+ rval = check_matrix(f);
+ TESTG(rval,CLEANUP,"Corrupted Matrix");
+ #endif /* DEBUG_FACTOR */
+
+ for (i = 0; i < nzcnt; i++)
+ {
+ x->indx[i] = urindx[i];
+ EGLPNUM_TYPENAME_EGlpNumCopy (x->coef[i], urcoef[i]);
+ delete_nonzero_col (f, urindx[i], urcind[i]);
+ urindx[i] = -1;
+ }
+ x->nzcnt = nzcnt;
+ ur_inf[row].nzcnt = 0;
+
+#ifdef TRACK_FACTOR
+ f->nzcnt_cur -= nzcnt;
+#endif
+
+ #ifdef DEBUG_FACTOR
+ rval = check_matrix(f);
+ TESTG(rval,CLEANUP,"Corrupted Matrix");
+ CLEANUP:
+ #endif /* DEBUG_FACTOR */
+ return rval;
+}
+
+static int create_column (
+ EGLPNUM_TYPENAME_factor_work * f,
+ EGLPNUM_TYPENAME_svector * a,
+ int col,
+ int *p_last_rank)
+{
+ int *rrank = f->rrank;
+ int nzcnt = a->nzcnt;
+ int *aindx = a->indx;
+ EGLPNUM_TYPE *acoef = a->coef;
+ int i;
+ int j;
+ int rval = 0;
+ int last_rank = -1;
+
+#ifdef TRACK_FACTOR
+ EGLPNUM_TYPE max;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (max);
+ EGLPNUM_TYPENAME_EGlpNumCopy (max, f->maxelem_cur);
+#endif /* TRACK_FACTOR */
+
+ last_rank = 0;
+
+ for (i = 0; i < nzcnt; i++)
+ {
+ rval = add_nonzero (f, aindx[i], col, acoef[i]);
+ CHECKRVALG (rval, CLEANUP);
+#ifdef TRACK_FACTOR
+ EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (max, acoef[i]);
+#endif /* TRACK_FACTOR */
+ j = rrank[aindx[i]];
+ if (j > last_rank)
+ last_rank = j;
+ }
+ *p_last_rank = last_rank;
+
+#ifdef TRACK_FACTOR
+ f->nzcnt_cur += nzcnt;
+ EGLPNUM_TYPENAME_EGlpNumCopy (f->maxelem_cur, max);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (max);
+#endif /* TRACK_FACTOR */
+
+ #ifdef DEBUG_FACTOR
+ rval = check_matrix(f);
+ TESTG(rval,CLEANUP,"Corrupted Matrix");
+ #endif /* DEBUG_FACTOR */
+
+ CLEANUP:
+ EG_RETURN (rval);
+}
+
+#ifdef UPDATE_STUDY
+static int column_rank (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int col)
+{
+ int *cperm = f->cperm;
+ int dim = f->dim;
+ int i;
+
+ for (i = 0; i < dim; i++)
+ {
+ if (cperm[i] == col)
+ {
+ return i;
+ }
+ }
+ return 0;
+}
+#endif
+
+static void shift_permutations (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int rank_p,
+ int rank_r)
+{
+ int *cperm = f->cperm;
+ int *crank = f->crank;
+ int *rperm = f->rperm;
+ int *rrank = f->rrank;
+ int col_p = cperm[rank_p];
+ int row_p = rperm[rank_p];
+ int i;
+
+ for (i = rank_p; i < rank_r; i++)
+ {
+ cperm[i] = cperm[i + 1];
+ crank[cperm[i]] = i;
+ rperm[i] = rperm[i + 1];
+ rrank[rperm[i]] = i;
+ }
+ cperm[rank_r] = col_p;
+ crank[col_p] = rank_r;
+ rperm[rank_r] = row_p;
+ rrank[row_p] = rank_r;
+}
+
+static int eliminate_row (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int rank_p,
+ int rank_r)
+{
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+ int *rperm = f->rperm;
+ int *cperm = f->cperm;
+ int *urindx = f->urindx;
+ EGLPNUM_TYPE *urcoef = f->urcoef;
+ int *erindx = f->erindx;
+ EGLPNUM_TYPE *ercoef = f->ercoef;
+ EGLPNUM_TYPE *work_coef = f->work_coef;
+ int er_freebeg = f->er_freebeg;
+ int er_space = f->er_space;
+ int beg;
+ int nzcnt;
+ int i;
+ int j;
+ int c;
+ int r;
+ EGLPNUM_TYPE pivot_mul;
+
+#ifdef TRACK_FACTOR
+ EGLPNUM_TYPE max;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (max);
+ EGLPNUM_TYPENAME_EGlpNumCopy (max, f->maxelem_cur);
+#endif /* TRACK_FACTOR */
+ EGLPNUM_TYPENAME_EGlpNumInitVar (pivot_mul);
+
+ for (i = rank_p; i < rank_r; i++)
+ {
+ c = cperm[i];
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (work_coef[c], f->fzero_tol)) /*
+ * if (work_coef[c] > fzero_tol || work_coef[c] < -fzero_tol) */
+ {
+ r = rperm[i];
+ beg = ur_inf[r].rbeg;
+ nzcnt = ur_inf[r].nzcnt;
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (pivot_mul, work_coef[c], urcoef[beg]);
+ EGLPNUM_TYPENAME_EGlpNumZero (work_coef[c]);
+ for (j = 1; j < nzcnt; j++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (work_coef[urindx[beg + j]], pivot_mul, urcoef[beg + j]); /* 0.85 */
+ }
+ if (er_freebeg >= er_space)
+ {
+ /* QSlog("no space in eliminate_row"); */
+#ifdef TRACK_FACTOR
+ EGLPNUM_TYPENAME_EGlpNumClearVar (max);
+#endif
+ EGLPNUM_TYPENAME_EGlpNumClearVar (pivot_mul);
+ return E_UPDATE_NOSPACE;
+ }
+ erindx[er_freebeg] = r;
+ EGLPNUM_TYPENAME_EGlpNumCopy (ercoef[er_freebeg], pivot_mul);
+#ifdef TRACK_FACTOR
+ EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (max, pivot_mul);
+#endif /* TRACK_FACTOR */
+ er_freebeg++;
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumZero (work_coef[c]);
+ }
+ }
+ f->er_freebeg = er_freebeg;
+#ifdef TRACK_FACTOR
+ EGLPNUM_TYPENAME_EGlpNumCopy (f->maxelem_cur, max);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (max);
+#endif /* TRACK_FACTOR */
+ EGLPNUM_TYPENAME_EGlpNumClearVar (pivot_mul);
+ return 0;
+}
+
+static int create_row (
+ EGLPNUM_TYPENAME_factor_work * f,
+ EGLPNUM_TYPE * a,
+ int row,
+ int minrank)
+{
+ int *cperm = f->cperm;
+ int dim = f->dim;
+ int i;
+ int j;
+ int rval = 0;
+
+#ifdef TRACK_FACTOR
+ EGLPNUM_TYPE max;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (max);
+ EGLPNUM_TYPENAME_EGlpNumCopy (max, f->maxelem_cur);
+#endif /* TRACK_FACTOR */
+
+ for (i = minrank; i < dim; i++)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (a[cperm[i]]))
+ {
+ j = cperm[i];
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (a[j], f->fzero_tol)) /*
+ * if (a[j] > fzero_tol || a[j] < -fzero_tol) */
+ {
+ rval = add_nonzero (f, row, j, a[j]);
+ CHECKRVALG (rval, CLEANUP);
+#ifdef TRACK_FACTOR
+ EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (max, a[j]);
+#endif /* TRACK_FACTOR */
+ }
+ EGLPNUM_TYPENAME_EGlpNumZero (a[j]);
+ }
+ }
+
+#ifdef TRACK_FACTOR
+ f->nzcnt_cur += f->ur_inf[row].nzcnt;
+ EGLPNUM_TYPENAME_EGlpNumCopy (f->maxelem_cur, max);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (max);
+#endif /* TRACK_FACTOR */
+
+ #ifdef DEBUG_FACTOR
+ rval = check_matrix(f);
+ TESTG(rval,CLEANUP,"Corrupted Matrix");
+ #endif /* DEBUG_FACTOR */
+ CLEANUP:
+ EG_RETURN (rval);
+}
+
+static void serow_delay (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int r,
+ int rank_r)
+{
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+ int *crank = f->crank;
+ int nzcnt;
+ int *indx;
+ int i;
+ int last;
+
+ do
+ {
+ r = f->rperm[crank[r]];
+ nzcnt = ur_inf[r].nzcnt;
+ indx = f->urindx + ur_inf[r].rbeg;
+ last = -1;
+ for (i = 1; i < nzcnt; i++)
+ {
+ r = indx[i];
+ if (ur_inf[r].delay++ == 0 && crank[r] < rank_r)
+ {
+ if (last >= 0)
+ {
+ serow_delay (f, last, rank_r);
+ }
+ last = r;
+ }
+ }
+ r = last;
+ } while (r >= 0);
+}
+
+static int serow_process (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int r,
+ EGLPNUM_TYPENAME_svector * newr,
+ int rank_r)
+{
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+ EGLPNUM_TYPE *work = f->work_coef;
+ int nzcnt;
+ int *indx;
+ EGLPNUM_TYPE *coef;
+ int i;
+ EGLPNUM_TYPE v;
+ int last;
+ int rval;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+
+ do
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (v, work[r]);
+ EGLPNUM_TYPENAME_EGlpNumZero (work[r]);
+ if (f->crank[r] >= rank_r)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (v, f->fzero_tol)) /*
+ * if (v > fzero_tol || v < -fzero_tol) */
+ {
+ /* stash this nonzero in the resulting row */
+#ifdef TRACK_FACTOR
+ EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (f->maxelem_cur, v);
+#endif /* TRACK_FACTOR */
+ newr->indx[newr->nzcnt] = r;
+ EGLPNUM_TYPENAME_EGlpNumCopy (newr->coef[newr->nzcnt], v);
+ newr->nzcnt++;
+ EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+ return 0;
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+ return 0;
+ }
+ }
+ r = f->rperm[f->crank[r]];
+ nzcnt = ur_inf[r].nzcnt;
+ indx = f->urindx + ur_inf[r].rbeg;
+ coef = f->urcoef + ur_inf[r].rbeg;
+ EGLPNUM_TYPENAME_EGlpNumDivTo (v, coef[0]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (v, f->fzero_tol)) /*
+ * if (v > fzero_tol || v < -fzero_tol) */
+ {
+ /* stash v in eta */
+ if (f->er_freebeg >= f->er_space)
+ {
+ /* QSlog("no space in eliminate_row"); */
+ EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+ return E_UPDATE_NOSPACE;
+ }
+ f->erindx[f->er_freebeg] = r;
+ EGLPNUM_TYPENAME_EGlpNumCopy (f->ercoef[f->er_freebeg], v);
+#ifdef TRACK_FACTOR
+ EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (f->maxelem_cur, v);
+#endif /* TRACK_FACTOR */
+ f->er_freebeg++;
+ }
+ last = -1;
+ for (i = 1; i < nzcnt; i++)
+ {
+ r = indx[i];
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (work[r], v, coef[i]);
+ if (--ur_inf[r].delay == 0)
+ {
+ if (last >= 0)
+ {
+ rval = serow_process (f, last, newr, rank_r);
+ if (rval)
+ {
+ EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+ return rval;
+ }
+ }
+ last = r;
+ }
+ }
+ r = last;
+ } while (r >= 0);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+ return 0;
+}
+
+static int sparse_eliminate_row (
+ EGLPNUM_TYPENAME_factor_work * f,
+ EGLPNUM_TYPENAME_svector * x,
+ int row_p,
+ int rank_r)
+{
+ EGLPNUM_TYPE *work = f->work_coef;
+ int xnzcnt = x->nzcnt;
+ int *xindx = x->indx;
+ EGLPNUM_TYPE *xcoef = x->coef;
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+ int *crank = f->crank;
+ int i;
+ int j;
+ int rval = 0;
+ EGLPNUM_TYPENAME_svector newr;
+
+ newr.indx = 0;
+ newr.coef = 0;
+
+ for (i = 0; i < xnzcnt; i++)
+ {
+ j = xindx[i];
+ if (ur_inf[j].delay++ == 0 && crank[j] < rank_r)
+ {
+ serow_delay (f, j, rank_r);
+ }
+ EGLPNUM_TYPENAME_EGlpNumCopy (work[j], xcoef[i]);
+ }
+
+ newr.nzcnt = 0;
+ ILL_SAFE_MALLOC (newr.indx, f->dim, int);
+
+ newr.coef = EGLPNUM_TYPENAME_EGlpNumAllocArray (f->dim);
+
+ for (i = 0; i < xnzcnt; i++)
+ {
+ j = xindx[i];
+ if (--ur_inf[j].delay == 0)
+ {
+ rval = serow_process (f, j, &newr, rank_r);
+ CHECKRVALG (rval, CLEANUP);
+ }
+ }
+
+ for (i = 0; i < newr.nzcnt; i++)
+ {
+ rval = add_nonzero (f, row_p, newr.indx[i], newr.coef[i]);
+ CHECKRVALG (rval, CLEANUP);
+ }
+
+#ifdef TRACK_FACTOR
+ f->nzcnt_cur += newr.nzcnt;
+#endif /* TRACK_FACTOR */
+
+CLEANUP:
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (newr.coef);
+ ILL_IFFREE (newr.indx, int);
+
+ /* Bico 031210 - chg from ILL_RETURN */
+ EG_RETURN (rval);
+}
+
+static int move_pivot_row (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int r,
+ int c)
+{
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf + r;
+ EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf;
+ int beg = ur_inf->rbeg;
+ int nzcnt = ur_inf->nzcnt;
+ int *urindx = f->urindx;
+ int *urcind = f->urcind;
+ int *ucrind = f->ucrind;
+ EGLPNUM_TYPE *urcoef = f->urcoef;
+ EGLPNUM_TYPE dt;
+ int it;
+ int i;
+
+ if (urindx[beg] == c)
+ return 0;
+ EGLPNUM_TYPENAME_EGlpNumInitVar (dt);
+
+ for (i = 1; i < nzcnt; i++)
+ {
+ if (urindx[beg + i] == c)
+ {
+ EGLPNUM_TYPENAME_EGLPNUM_SWAP (urcoef[beg], urcoef[beg + i], dt);
+ ILL_SWAP (urcind[beg], urcind[beg + i], it);
+ urindx[beg + i] = urindx[beg];
+ urindx[beg] = c;
+ ucrind[uc_inf[c].cbeg + urcind[beg]] = 0;
+ ucrind[uc_inf[urindx[beg + i]].cbeg + urcind[beg + i]] = i;
+ EGLPNUM_TYPENAME_EGlpNumClearVar (dt);
+ return 0;
+ }
+ }
+ MESSAGE (__QS_SB_VERB, "pivot row nonzero not found");
+ EGLPNUM_TYPENAME_EGlpNumClearVar (dt);
+ return E_UPDATE_SINGULAR_ROW;
+}
+
+static int move_pivot_col (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int c,
+ int r)
+{
+ EGLPNUM_TYPENAME_uc_info *uc_inf = f->uc_inf + c;
+ EGLPNUM_TYPENAME_ur_info *ur_inf = f->ur_inf;
+ int beg = uc_inf->cbeg;
+ int nzcnt = uc_inf->nzcnt;
+ int *ucindx = f->ucindx;
+ int *ucrind = f->ucrind;
+ int *urcind = f->urcind;
+ EGLPNUM_TYPE *uccoef = f->uccoef;
+ EGLPNUM_TYPE dt;
+ int i, it;
+
+ if (ucindx[beg] == r)
+ return 0;
+ EGLPNUM_TYPENAME_EGlpNumInitVar (dt);
+
+ for (i = 1; i < nzcnt; i++)
+ {
+ if (ucindx[beg + i] == r)
+ {
+ EGLPNUM_TYPENAME_EGLPNUM_SWAP (uccoef[beg], uccoef[beg + i], dt);
+ ILL_SWAP (ucrind[beg], ucrind[beg + i], it);
+ ucindx[beg + i] = ucindx[beg];
+ ucindx[beg] = r;
+ urcind[ur_inf[r].rbeg + ucrind[beg]] = 0;
+ urcind[ur_inf[ucindx[beg + i]].rbeg + ucrind[beg + i]] = i;
+ EGLPNUM_TYPENAME_EGlpNumClearVar (dt);
+ return 0;
+ }
+ }
+ MESSAGE(__QS_SB_VERB, "pivot col nonzero not found");
+ EGLPNUM_TYPENAME_EGlpNumClearVar (dt);
+ return E_UPDATE_SINGULAR_COL;
+}
+
+static int move_pivot (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int rank_r)
+{
+ int r = f->rperm[rank_r];
+ int c = f->cperm[rank_r];
+ int rval = 0;
+
+ rval = move_pivot_row (f, r, c);
+ CHECKRVALG (rval, CLEANUP);
+
+ #ifdef DEBUG_FACTOR
+ rval = check_matrix(f);
+ TESTG(rval,CLEANUP,"Corrupted Matrix");
+ #endif /* DEBUG_FACTOR */
+
+ rval = move_pivot_col (f, c, r);
+ if(rval != E_UPDATE_SINGULAR_COL) CHECKRVALG (rval, CLEANUP);
+ else goto CLEANUP;
+
+ #ifdef DEBUG_FACTOR
+ rval = check_matrix(f);
+ TESTG(rval,CLEANUP,"Corrupted Matrix");
+ #endif /* DEBUG_FACTOR */
+
+ CLEANUP:
+ if(rval != E_UPDATE_SINGULAR_COL) EG_RETURN (rval); /* Bico 031209 - chg from RETURN */
+ return rval;
+}
+
+int EGLPNUM_TYPENAME_ILLfactor_update (
+ EGLPNUM_TYPENAME_factor_work * f,
+ EGLPNUM_TYPENAME_svector * a,
+ int col_p,
+ int *p_refact)
+{
+ int row_p;
+ int rank_r = 0;
+ int rank_p = 0;
+ int rval = 0;
+ int nzcnt;
+ int *aindx;
+ EGLPNUM_TYPE *acoef;
+ EGLPNUM_TYPE *work_coef = f->work_coef;
+
+#ifdef TRACK_FACTOR
+#ifdef NOTICE_BLOWUP
+ EGLPNUM_TYPE tmpsize;
+#endif
+#endif
+ int i;
+
+#ifdef RECORD
+ {
+ EGioPrintf (fsave, "u %d %d", col_p, a->nzcnt);
+ for (i = 0; i < a->nzcnt; i++)
+ {
+ EGioPrintf (fsave, " %d %.16e", a->indx[i], EGLPNUM_TYPENAME_EGlpNumToLf (a->coef[i]));
+ }
+ EGioPrintf (fsave, "\n");
+ EGioFlush (fsave);
+ }
+#endif /* RECORD */
+
+#ifdef DEBUG_FACTOR
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLfactor_update col %d:", col_p);
+ for (i = 0; i < a->nzcnt; i++)
+ {
+ QSlog(" %.3f*%d", EGLPNUM_TYPENAME_EGlpNumToLf (a->coef[i]), a->indx[i]);
+ }
+ }
+#endif /* DEBUG_FACTOR */
+
+ #ifdef DEBUG_FACTOR
+ rval = check_matrix(f);
+ TESTG(rval,CLEANUP,"Corrupted Matrix");
+ #endif /* DEBUG_FACTOR */
+
+ if (f->etacnt >= f->etamax)
+ {
+ *p_refact = 1;
+ return 0;
+ }
+
+#ifdef UPDATE_STUDY
+ nupdate++;
+#endif
+
+ row_p = f->ucindx[f->uc_inf[col_p].cbeg];
+
+ rval = delete_column (f, col_p);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = create_column (f, a, col_p, &rank_r);
+ /* if (rval) QSlog("create_column failed"); */
+ CHECKRVALG (rval, CLEANUP);
+
+ rank_p = f->crank[col_p];
+#ifdef UPDATE_STUDY
+ if (rank_p != f->rrank[row_p] || rank_p != column_rank (f, col_p))
+ {
+ QSlog("rank_p %d rrank[row_p] %d column_rank(f,col_p) %d",
+ rank_p, f->rrank[row_p], column_rank (f, col_p));
+ }
+ if (rank_r > rank_p)
+ {
+ permshifttot += rank_r - rank_p;
+ }
+ for (i = 0; i < a->nzcnt; i++)
+ {
+ if (f->rrank[a->indx[i]] > rank_p)
+ colspiketot++;
+ }
+ for (i = 0; i < f->ur_inf[row_p].nzcnt; i++)
+ {
+ if (f->crank[f->urindx[f->ur_inf[row_p].rbeg + i]] <= rank_r &&
+ f->crank[f->urindx[f->ur_inf[row_p].rbeg + i]] != rank_p)
+ {
+ rowspiketot++;
+ }
+ }
+#endif
+
+ shift_permutations (f, rank_p, rank_r);
+
+ rval = delete_row (f, row_p, &f->xtmp);
+ CHECKRVALG(rval,CLEANUP);
+
+ f->er_inf[f->etacnt].rbeg = f->er_freebeg;
+ f->er_inf[f->etacnt].r = row_p;
+
+ if (f->xtmp.nzcnt >= SPARSE_FACTOR * f->dim)
+ {
+ nzcnt = f->xtmp.nzcnt;
+ aindx = f->xtmp.indx;
+ acoef = f->xtmp.coef;
+
+ for (i = 0; i < nzcnt; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (work_coef[aindx[i]], acoef[i]);
+ }
+
+ rval = eliminate_row (f, rank_p, rank_r);
+ /* if (rval) QSlog("eliminate_row failed"); */
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = create_row (f, f->work_coef, row_p, rank_r);
+ /* if (rval) QSlog("create_row failed"); */
+ CHECKRVALG (rval, CLEANUP);
+ }
+ else
+ {
+ rval = sparse_eliminate_row (f, &f->xtmp, row_p, rank_r);
+ /* if (rval) QSlog("sparse_eliminate_row failed"); */
+ CHECKRVALG (rval, CLEANUP);
+ }
+
+ if (f->er_freebeg - f->er_inf[f->etacnt].rbeg > 0)
+ {
+ f->er_inf[f->etacnt].nzcnt = f->er_freebeg - f->er_inf[f->etacnt].rbeg;
+#ifdef TRACK_FACTOR
+ f->nzcnt_cur += f->er_inf[f->etacnt].nzcnt;
+#endif /* TRACK_FACTOR */
+#ifdef UPDATE_STUDY
+ leftetatot += f->er_inf[f->etacnt].nzcnt;
+#endif
+
+#ifdef SORT_RESULTS
+ sort_vector2 (f->er_inf[f->etacnt].nzcnt,
+ f->erindx + f->er_inf[f->etacnt].rbeg,
+ f->ercoef + f->er_inf[f->etacnt].rbeg);
+#endif
+
+ f->etacnt++;
+ }
+
+ rval = move_pivot (f, rank_r);
+ /* if (rval) QSlog("move_pivot failed"); */
+ if(rval != E_UPDATE_SINGULAR_COL) CHECKRVALG (rval, CLEANUP);
+ else goto CLEANUP;
+
+#ifdef UPDATE_DEBUG
+ QSlog("Updated factorization:");
+#if (UPDATE_DEBUG+0>1)
+ dump_matrix (f, 0);
+#endif
+#endif /* UPDATE_DEBUG */
+
+#ifdef TRACK_FACTOR
+#ifdef NOTICE_BLOWUP
+ EGLPNUM_TYPENAME_EGlpNumInitVar (tmpsize);
+ EGLPNUM_TYPENAME_EGlpNumSet (tmpsize, f->updmaxmult);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (tmpsize, f->maxelem_orig);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (tmpsize, f->maxelem_cur))
+ {
+/* Bico - comment out for dist
+ QSlog("factor_update blowup max cur %e max orig %e",
+ f->maxelem_cur, f->maxelem_orig);
+*/
+ EGLPNUM_TYPENAME_EGlpNumClearVar (tmpsize);
+ return E_FACTOR_BLOWUP;
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (tmpsize);
+#endif /* NOTICE_BLOWUP */
+#endif
+#ifdef UPDATE_STATS
+ dump_factor_stats (f);
+#endif
+CLEANUP:
+ if(rval != E_UPDATE_SINGULAR_COL) EG_RETURN (rval); /* Bico 031209 - chg from RETURN */
+ return rval;
+}
diff --git a/qsopt_ex/factor.h b/qsopt_ex/factor.h
new file mode 100644
index 0000000..2f2f247
--- /dev/null
+++ b/qsopt_ex/factor.h
@@ -0,0 +1,206 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCSINFO $Id: factor_EGLPNUM_TYPENAME.h,v 1.3 2003/11/05 16:57:39 meven Exp $ */
+#ifndef EGLPNUM_TYPENAME___QS_FACTOR_H_
+#define EGLPNUM_TYPENAME___QS_FACTOR_H_
+
+#include "basicdefs.h"
+#include "dstruct_EGLPNUM_TYPENAME.h"
+
+typedef char EGLPNUM_TYPENAME_QSbool;
+
+typedef struct EGLPNUM_TYPENAME_uc_info
+{
+ int cbeg;
+ int nzcnt;
+ int next;
+ int prev;
+ int delay;
+}
+EGLPNUM_TYPENAME_uc_info;
+
+typedef struct EGLPNUM_TYPENAME_ur_info
+{
+ EGLPNUM_TYPE max;
+ int rbeg;
+ int nzcnt;
+ int pivcnt;
+ int next;
+ int prev;
+ int delay;
+}
+EGLPNUM_TYPENAME_ur_info;
+
+typedef struct EGLPNUM_TYPENAME_lc_info
+{
+ int cbeg;
+ int nzcnt;
+ int c;
+ int crank;
+ int delay;
+}
+EGLPNUM_TYPENAME_lc_info;
+
+typedef struct EGLPNUM_TYPENAME_lr_info
+{
+ int rbeg;
+ int nzcnt;
+ int r;
+ int rrank;
+ int delay;
+}
+EGLPNUM_TYPENAME_lr_info;
+
+typedef struct EGLPNUM_TYPENAME_er_info
+{
+ int rbeg;
+ int nzcnt;
+ int r;
+}
+EGLPNUM_TYPENAME_er_info;
+
+typedef struct EGLPNUM_TYPENAME_factor_work
+{
+ int max_k;
+ EGLPNUM_TYPE fzero_tol;
+ EGLPNUM_TYPE szero_tol;
+ EGLPNUM_TYPE partial_tol;
+ double ur_space_mul;
+ double uc_space_mul;
+ double lc_space_mul;
+ double lr_space_mul;
+ double er_space_mul;
+ double grow_mul;
+ int p;
+ int etamax;
+ double minmult;
+ double maxmult;
+ double updmaxmult;
+ double dense_fract;
+ int dense_min;
+
+ EGLPNUM_TYPE maxelem_orig;
+ int nzcnt_orig;
+ EGLPNUM_TYPE maxelem_factor;
+ int nzcnt_factor;
+ EGLPNUM_TYPE maxelem_cur;
+ int nzcnt_cur;
+
+ EGLPNUM_TYPE partial_cur;
+
+ int dim;
+ int stage;
+ int nstages;
+ int etacnt;
+ EGLPNUM_TYPE *work_coef;
+ int *work_indx;
+ EGLPNUM_TYPENAME_uc_info *uc_inf;
+ EGLPNUM_TYPENAME_ur_info *ur_inf;
+ EGLPNUM_TYPENAME_lc_info *lc_inf;
+ EGLPNUM_TYPENAME_lr_info *lr_inf;
+ EGLPNUM_TYPENAME_er_info *er_inf;
+ int *ucindx; /* row index for column data */
+ int *ucrind; /* index of column in row data */
+ EGLPNUM_TYPE *uccoef; /* coefficient for column data */
+ int *urindx; /* col index for row data */
+ int *urcind; /* index of row in column data */
+ EGLPNUM_TYPE *urcoef; /* coefficient for row data */
+ int *lcindx; /* row index for L data */
+ EGLPNUM_TYPE *lccoef; /* coefficient for L row data */
+ int *lrindx; /* col index for L data */
+ EGLPNUM_TYPE *lrcoef; /* coefficient for L col data */
+ int *erindx; /* col index for eta data */
+ EGLPNUM_TYPE *ercoef; /* coefficient for eta data */
+ int *rperm;
+ int *rrank;
+ int *cperm;
+ int *crank;
+ EGLPNUM_TYPENAME_svector xtmp;
+ int ur_freebeg;
+ int ur_space;
+ int uc_freebeg;
+ int uc_space;
+ int lc_freebeg;
+ int lc_space;
+ int lr_freebeg;
+ int lr_space;
+ int er_freebeg;
+ int er_space;
+
+ int *p_nsing;
+ int **p_singr;
+ int **p_singc;
+
+ EGLPNUM_TYPE *dmat;
+ int drows;
+ int dcols;
+ int dense_base;
+}
+EGLPNUM_TYPENAME_factor_work;
+
+void EGLPNUM_TYPENAME_ILLfactor_init_factor_work (
+ EGLPNUM_TYPENAME_factor_work * f),
+ EGLPNUM_TYPENAME_ILLfactor_free_factor_work (
+ EGLPNUM_TYPENAME_factor_work * f),
+ EGLPNUM_TYPENAME_ILLfactor_ftran (
+ EGLPNUM_TYPENAME_factor_work * f,
+ EGLPNUM_TYPENAME_svector * a,
+ EGLPNUM_TYPENAME_svector * x),
+ EGLPNUM_TYPENAME_ILLfactor_ftran_update (
+ EGLPNUM_TYPENAME_factor_work * f,
+ EGLPNUM_TYPENAME_svector * a,
+ EGLPNUM_TYPENAME_svector * upd,
+ EGLPNUM_TYPENAME_svector * x),
+ EGLPNUM_TYPENAME_ILLfactor_btran (
+ EGLPNUM_TYPENAME_factor_work * f,
+ EGLPNUM_TYPENAME_svector * a,
+ EGLPNUM_TYPENAME_svector * x);
+
+int EGLPNUM_TYPENAME_ILLfactor_create_factor_work (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int dim),
+ EGLPNUM_TYPENAME_ILLfactor_set_factor_iparam (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int param,
+ int val),
+ EGLPNUM_TYPENAME_ILLfactor_set_factor_dparam (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int param,
+ EGLPNUM_TYPE val),
+ EGLPNUM_TYPENAME_ILLfactor (
+ EGLPNUM_TYPENAME_factor_work * f,
+ int *basis,
+ int *cbeg,
+ int *clen,
+ int *cindx,
+ EGLPNUM_TYPE * ccoef,
+ int *p_nsing,
+ int **p_singr,
+ int **p_singc),
+ EGLPNUM_TYPENAME_ILLfactor_update (
+ EGLPNUM_TYPENAME_factor_work * f,
+ EGLPNUM_TYPENAME_svector * a,
+ int col,
+ int *p_refact);
+
+#endif /* EGLPNUM_TYPENAME___QS_FACTOR_H_ */
diff --git a/qsopt_ex/fct.c b/qsopt_ex/fct.c
new file mode 100644
index 0000000..4a88afe
--- /dev/null
+++ b/qsopt_ex/fct.c
@@ -0,0 +1,2501 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: fct.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+static int TRACE = 0;
+
+//#define FCT_DEBUG 10
+#define FCT_DEBUG 0
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "allocrus.h"
+#include "eg_lpnum.h"
+#include "eg_io.h"
+#include "except.h"
+#include "trace.h"
+#include "util.h"
+
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+#include "stddefs.h"
+#include "basis_EGLPNUM_TYPENAME.h"
+#include "fct_EGLPNUM_TYPENAME.h"
+#include "price_EGLPNUM_TYPENAME.h"
+#include "ratio_EGLPNUM_TYPENAME.h"
+#include "dstruct_EGLPNUM_TYPENAME.h"
+
+
+EGLPNUM_TYPENAME_bndinfo *EGLPNUM_TYPENAME_ILLfct_new_bndinfo (
+ void)
+{
+ EGLPNUM_TYPENAME_bndinfo *nbnd = (EGLPNUM_TYPENAME_bndinfo *) malloc (sizeof (EGLPNUM_TYPENAME_bndinfo));
+
+ if (!nbnd)
+ {
+ QSlog("not enough memory, in %s", __func__);
+ exit (1);
+ }
+ EGLPNUM_TYPENAME_EGlpNumInitVar ((nbnd->pbound));
+ EGLPNUM_TYPENAME_EGlpNumInitVar ((nbnd->cbound));
+ return nbnd;
+}
+
+void EGLPNUM_TYPENAME_ILLfct_free_bndinfo (
+ EGLPNUM_TYPENAME_bndinfo * binfo)
+{
+ EGLPNUM_TYPENAME_EGlpNumClearVar ((binfo->pbound));
+ EGLPNUM_TYPENAME_EGlpNumClearVar ((binfo->cbound));
+ ILL_IFFREE (binfo, EGLPNUM_TYPENAME_bndinfo);
+ return;
+}
+
+static int compute_zA1 (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * z,
+ EGLPNUM_TYPENAME_svector * zA,
+ EGLPNUM_TYPE ztoler),
+/*
+ compute_zA2 (EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * z,
+ EGLPNUM_TYPENAME_svector * zA,
+ const EGLPNUM_TYPE* ztoler), */
+ compute_zA3 (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * z,
+ EGLPNUM_TYPENAME_svector * zA,
+ EGLPNUM_TYPE ztoler),
+ expand_var_bounds (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPE ftol,
+ int *chgb),
+ expand_var_coefs (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPE ftol,
+ int *chgc);
+
+static void update_piv_values (
+ EGLPNUM_TYPENAME_count_struct * c,
+ int phase,
+ const EGLPNUM_TYPE piv),
+/* copy_vectors (EGLPNUM_TYPENAME_svector * a,
+ EGLPNUM_TYPENAME_svector * b),*/
+ add_vectors (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * a,
+ EGLPNUM_TYPENAME_svector * b,
+ EGLPNUM_TYPENAME_svector * c,
+ const EGLPNUM_TYPE t);
+
+static double my_rand (
+ int bound,
+ ILLrandstate * r);
+
+
+void EGLPNUM_TYPENAME_ILLfct_load_workvector (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * s)
+{
+ int i;
+
+ for (i = 0; i < s->nzcnt; i++)
+ {
+ lp->work.indx[i] = s->indx[i];
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->work.coef[s->indx[i]], s->coef[i]);
+ }
+ lp->work.nzcnt = s->nzcnt;
+}
+
+void EGLPNUM_TYPENAME_ILLfct_zero_workvector (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ int i;
+
+ for (i = 0; i < lp->work.nzcnt; i++)
+ EGLPNUM_TYPENAME_EGlpNumZero (lp->work.coef[lp->work.indx[i]]);
+ lp->work.nzcnt = 0;
+}
+
+void EGLPNUM_TYPENAME_ILLfct_set_variable_type (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ int j;
+
+ for (j = 0; j < lp->ncols; j++)
+ {
+
+ if (lp->matcnt[j] == 1 && lp->O->rowmap[lp->matind[lp->matbeg[j]]] == j)
+ lp->vclass[j] = CLASS_LOGICAL;
+ else
+ lp->vclass[j] = CLASS_STRUCT;
+ switch ((EGLPNUM_TYPENAME_EGlpNumIsEqqual (lp->uz[j], EGLPNUM_TYPENAME_INFTY) ? 1U : 0U) |
+ (EGLPNUM_TYPENAME_EGlpNumIsEqqual (lp->lz[j], EGLPNUM_TYPENAME_NINFTY) ? 2U : 0U))
+ {
+ case 0:
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (lp->lz[j], lp->uz[j]))
+ lp->vtype[j] = VBOUNDED;
+ else if (!EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (lp->lz[j]) &&
+ (lp->vclass[j] == CLASS_LOGICAL))
+ lp->vtype[j] = VARTIFICIAL;
+ else
+ lp->vtype[j] = VFIXED;
+ break;
+ case 3:
+ lp->vtype[j] = VFREE;
+ break;
+ case 1:
+ lp->vtype[j] = VLOWER;
+ break;
+ case 2:
+ lp->vtype[j] = VUPPER;
+ break;
+ }
+ }
+}
+
+/* compute various vectors */
+
+void EGLPNUM_TYPENAME_ILLfct_compute_pobj (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ int i, j;
+ int col;
+ EGLPNUM_TYPE sum;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (sum);
+ EGLPNUM_TYPENAME_EGlpNumZero (sum);
+
+ for (i = 0; i < lp->nrows; i++)
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, lp->cz[lp->baz[i]], lp->xbz[i]);
+
+ for (j = 0; j < lp->nnbasic; j++)
+ {
+ col = lp->nbaz[j];
+ if (lp->vstat[col] == STAT_UPPER)
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, lp->cz[col], lp->uz[col]);
+ else if (lp->vstat[col] == STAT_LOWER)
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, lp->cz[col], lp->lz[col]);
+ }
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->pobjval, sum);
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->objval, sum);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (sum);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_compute_dobj (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ int i, j;
+ int col;
+ EGLPNUM_TYPE sum;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (sum);
+ EGLPNUM_TYPENAME_EGlpNumZero (sum);
+
+ for (i = 0; i < lp->nrows; i++)
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, lp->piz[i], lp->bz[i]);
+
+ for (j = 0; j < lp->nnbasic; j++)
+ {
+ col = lp->nbaz[j];
+ if (lp->vstat[col] == STAT_UPPER)
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, lp->dz[j], lp->uz[col]);
+ else if (lp->vstat[col] == STAT_LOWER)
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, lp->dz[j], lp->lz[col]);
+ }
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->dobjval, sum);
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->objval, sum);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (sum);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_compute_xbz (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ int i, j, r;
+ int col, mcnt, mbeg;
+ EGLPNUM_TYPENAME_svector *srhs = &(lp->srhs);
+ EGLPNUM_TYPENAME_svector *ssoln = &(lp->ssoln);
+ EGLPNUM_TYPE xval;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (xval);
+
+ for (i = 0; i < lp->nrows; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumZero (lp->xbz[i]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (srhs->coef[i], lp->bz[i]);
+ }
+ for (j = 0; j < lp->nnbasic; j++)
+ {
+ col = lp->nbaz[j];
+ EGLPNUM_TYPENAME_EGlpNumZero (xval);
+ if (lp->vstat[col] == STAT_UPPER && EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (lp->uz[col]))
+ EGLPNUM_TYPENAME_EGlpNumCopy (xval, lp->uz[col]);
+ else if (lp->vstat[col] == STAT_LOWER && EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (lp->lz[col]))
+ EGLPNUM_TYPENAME_EGlpNumCopy (xval, lp->lz[col]);
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (xval))
+ {
+ mcnt = lp->matcnt[col];
+ mbeg = lp->matbeg[col];
+ for (i = 0; i < mcnt; i++)
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (srhs->coef[lp->matind[mbeg + i]], xval,
+ lp->matval[mbeg + i]);
+ }
+ }
+ for (i = 0, r = 0; i < lp->nrows; i++)
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (srhs->coef[i]))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (srhs->coef[r], srhs->coef[i]);
+ srhs->indx[r] = i;
+ r++;
+ }
+ srhs->nzcnt = r;
+
+ EGLPNUM_TYPENAME_ILLbasis_column_solve (lp, srhs, ssoln);
+ for (i = 0; i < ssoln->nzcnt; i++)
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->xbz[ssoln->indx[i]], ssoln->coef[i]);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (xval);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_compute_piz (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ int i, r;
+ EGLPNUM_TYPENAME_svector *srhs = &(lp->srhs);
+ EGLPNUM_TYPENAME_svector *ssoln = &(lp->ssoln);
+
+ for (i = 0, r = 0; i < lp->nrows; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumZero (lp->piz[i]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (lp->cz[lp->baz[i]]))
+ {
+ srhs->indx[r] = i;
+ EGLPNUM_TYPENAME_EGlpNumCopy (srhs->coef[r], lp->cz[lp->baz[i]]);
+ r++;
+ }
+ }
+ srhs->nzcnt = r;
+
+ EGLPNUM_TYPENAME_ILLbasis_row_solve (lp, srhs, ssoln);
+ for (i = 0; i < ssoln->nzcnt; i++)
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->piz[ssoln->indx[i]], ssoln->coef[i]);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_compute_dz (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ int i, j;
+ int col;
+ int mcnt, mbeg;
+ EGLPNUM_TYPE sum;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (sum);
+
+ for (j = 0; j < lp->nnbasic; j++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumZero (sum);
+ col = lp->nbaz[j];
+ mcnt = lp->matcnt[col];
+ mbeg = lp->matbeg[col];
+ for (i = 0; i < mcnt; i++)
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, lp->piz[lp->matind[mbeg + i]],
+ lp->matval[mbeg + i]);
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (lp->dz[j], lp->cz[col], sum);
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (sum);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_compute_phaseI_xbz (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ int i, j, r;
+ int col, mcnt, mbeg;
+ EGLPNUM_TYPENAME_svector *srhs = &(lp->srhs);
+ EGLPNUM_TYPENAME_svector *ssoln = &(lp->ssoln);
+
+ for (i = 0; i < lp->nrows; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumZero (lp->xbz[i]);
+ EGLPNUM_TYPENAME_EGlpNumZero (srhs->coef[i]);
+ }
+ for (j = 0; j < lp->nnbasic; j++)
+ {
+ col = lp->nbaz[j];
+
+ if (lp->dfeas[j])
+ {
+ mcnt = lp->matcnt[col];
+ mbeg = lp->matbeg[col];
+ if (lp->dfeas[j] == -1)
+ for (i = 0; i < mcnt; i++)
+ EGLPNUM_TYPENAME_EGlpNumSubTo (srhs->coef[lp->matind[mbeg + i]], lp->matval[mbeg + i]);
+ else
+ for (i = 0; i < mcnt; i++)
+ EGLPNUM_TYPENAME_EGlpNumAddTo (srhs->coef[lp->matind[mbeg + i]], lp->matval[mbeg + i]);
+ }
+ }
+ for (i = 0, r = 0; i < lp->nrows; i++)
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (srhs->coef[i]))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (srhs->coef[r], srhs->coef[i]);
+ srhs->indx[r] = i;
+ r++;
+ }
+ srhs->nzcnt = r;
+
+ EGLPNUM_TYPENAME_ILLbasis_column_solve (lp, srhs, ssoln);
+ for (i = 0; i < ssoln->nzcnt; i++)
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->xbz[ssoln->indx[i]], ssoln->coef[i]);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_compute_phaseI_piz (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ int i, r;
+ EGLPNUM_TYPENAME_svector *srhs = &(lp->srhs);
+ EGLPNUM_TYPENAME_svector *ssoln = &(lp->ssoln);
+
+ for (i = 0, r = 0; i < lp->nrows; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumZero (lp->pIpiz[i]);
+ if (lp->bfeas[i] != 0)
+ {
+ srhs->indx[r] = i;
+ EGLPNUM_TYPENAME_EGlpNumSet (srhs->coef[r], (double) lp->bfeas[i]);
+ r++;
+ }
+ }
+ srhs->nzcnt = r;
+
+ EGLPNUM_TYPENAME_ILLbasis_row_solve (lp, srhs, ssoln);
+ for (i = 0; i < ssoln->nzcnt; i++)
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->pIpiz[ssoln->indx[i]], ssoln->coef[i]);
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_P1PINZ, ssoln->nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_compute_phaseI_dz (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ int i, j;
+ int col;
+ int mcnt, mbeg;
+ EGLPNUM_TYPE sum;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (sum);
+ ILL_IFTRACE ("%s\n", __func__);
+
+ for (j = 0; j < lp->nnbasic; j++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumZero (sum);
+ col = lp->nbaz[j];
+ mcnt = lp->matcnt[col];
+ mbeg = lp->matbeg[col];
+ for (i = 0; i < mcnt; i++)
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, lp->pIpiz[lp->matind[mbeg + i]],
+ lp->matval[mbeg + i]);
+ EGLPNUM_TYPENAME_EGlpNumCopyNeg (lp->pIdz[j], sum);
+ ILL_IFTRACE ("%d:%d:%lf:%la\n", j, col, EGLPNUM_TYPENAME_EGlpNumToLf (sum),
+ EGLPNUM_TYPENAME_EGlpNumToLf (sum));
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (sum);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_compute_yz (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * yz,
+ EGLPNUM_TYPENAME_svector * updz,
+ int col)
+{
+ EGLPNUM_TYPENAME_svector a;
+
+ a.nzcnt = lp->matcnt[col];
+ a.indx = &(lp->matind[lp->matbeg[col]]);
+ a.coef = &(lp->matval[lp->matbeg[col]]);
+
+ EGLPNUM_TYPENAME_ILLfactor_set_factor_dparam (lp->f, QS_FACTOR_SZERO_TOL, EGLPNUM_TYPENAME_PIVZ_TOLER);
+ if (updz)
+ EGLPNUM_TYPENAME_ILLbasis_column_solve_update (lp, &a, updz, yz);
+ else
+ EGLPNUM_TYPENAME_ILLbasis_column_solve (lp, &a, yz);
+ EGLPNUM_TYPENAME_ILLfactor_set_factor_dparam (lp->f, QS_FACTOR_SZERO_TOL, EGLPNUM_TYPENAME_SZERO_TOLER);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_compute_zz (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * zz,
+ int row)
+{
+ EGLPNUM_TYPENAME_ILLfct_compute_binvrow (lp, zz, row, EGLPNUM_TYPENAME_PIVZ_TOLER);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_compute_binvrow (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * zz,
+ int row,
+ EGLPNUM_TYPE ztoler)
+{
+ EGLPNUM_TYPENAME_svector a;
+ EGLPNUM_TYPE e;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (e);
+ EGLPNUM_TYPENAME_EGlpNumOne (e);
+
+ a.nzcnt = 1;
+ a.coef = &e;
+ a.indx = &row;
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (ztoler))
+ EGLPNUM_TYPENAME_ILLfactor_set_factor_dparam (lp->f, QS_FACTOR_SZERO_TOL, ztoler);
+ EGLPNUM_TYPENAME_ILLbasis_row_solve (lp, &a, zz);
+ if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (ztoler))
+ EGLPNUM_TYPENAME_ILLfactor_set_factor_dparam (lp->f, QS_FACTOR_SZERO_TOL, EGLPNUM_TYPENAME_SZERO_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (e);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_compute_psteep_upv (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * swz)
+{
+ EGLPNUM_TYPENAME_ILLbasis_row_solve (lp, &(lp->yjz), swz);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_compute_dsteep_upv (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * swz)
+{
+ EGLPNUM_TYPENAME_ILLbasis_column_solve (lp, &(lp->zz), swz);
+}
+
+static int compute_zA1 (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * z,
+ EGLPNUM_TYPENAME_svector * zA,
+ EGLPNUM_TYPE ztoler)
+{
+ int rval = 0;
+ int i, j, nz = 0;
+ int col, mcnt, mbeg;
+ EGLPNUM_TYPE sum;
+ EGLPNUM_TYPE *v = 0;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (sum);
+ v = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+
+ for (i = 0; i < lp->nrows; i++)
+ EGLPNUM_TYPENAME_EGlpNumZero (v[i]);
+ for (i = 0; i < z->nzcnt; i++)
+ EGLPNUM_TYPENAME_EGlpNumCopy (v[z->indx[i]], z->coef[i]);
+
+ for (j = 0; j < lp->nnbasic; j++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumZero (sum);
+ col = lp->nbaz[j];
+ mcnt = lp->matcnt[col];
+ mbeg = lp->matbeg[col];
+ for (i = 0; i < mcnt; i++)
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, v[lp->matind[mbeg + i]], lp->matval[mbeg + i]);
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (sum, ztoler))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (zA->coef[nz], sum);
+ zA->indx[nz] = j;
+ nz++;
+ }
+ }
+ zA->nzcnt = nz;
+
+ EGLPNUM_TYPENAME_EGlpNumClearVar (sum);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (v);
+ EG_RETURN (rval);
+}
+
+
+static int compute_zA3 (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * z,
+ EGLPNUM_TYPENAME_svector * zA,
+ EGLPNUM_TYPE ztoler)
+{
+ int rval = 0;
+ int i, j, k, ix;
+ int nz = 0;
+ int row, col;
+ int rcnt, rbeg;
+ EGLPNUM_TYPE val;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (val);
+ k = 0;
+ for (i = 0; i < z->nzcnt; i++)
+ {
+ row = z->indx[i];
+ EGLPNUM_TYPENAME_EGlpNumCopy (val, z->coef[i]);
+ rcnt = lp->rowcnt[row];
+ rbeg = lp->rowbeg[row];
+ for (j = 0; j < rcnt; j++)
+ {
+ col = lp->rowind[rbeg + j];
+ if (lp->vstat[col] != STAT_BASIC)
+ {
+ ix = lp->vindex[col];
+ if (lp->iwork[ix] == 0)
+ {
+ lp->iwork[ix] = 1;
+ lp->work.indx[k++] = ix;
+ }
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (lp->work.coef[ix], val, lp->rowval[rbeg + j]);
+ }
+ }
+ }
+ for (j = 0; j < k; j++)
+ {
+ ix = lp->work.indx[j];
+ EGLPNUM_TYPENAME_EGlpNumCopy (val, lp->work.coef[ix]);
+ EGLPNUM_TYPENAME_EGlpNumZero (lp->work.coef[ix]);
+ lp->iwork[ix] = 0;
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (val, ztoler))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (zA->coef[nz], val);
+ zA->indx[nz] = ix;
+ nz++;
+ }
+ }
+ zA->nzcnt = nz;
+ EGLPNUM_TYPENAME_EGlpNumClearVar (val);
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLfct_compute_zA (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * z,
+ EGLPNUM_TYPENAME_svector * zA)
+{
+ if (z->nzcnt < lp->nrows / 2)
+ return compute_zA3 (lp, z, zA, EGLPNUM_TYPENAME_PIVZ_TOLER);
+ else
+ return compute_zA1 (lp, z, zA, EGLPNUM_TYPENAME_PIVZ_TOLER);
+}
+
+/* compute v^T A */
+void EGLPNUM_TYPENAME_ILLfct_compute_vA (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * v,
+ EGLPNUM_TYPE * vA)
+{
+ int i, j;
+ int row, col;
+ int rcnt, rbeg;
+ EGLPNUM_TYPE val;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (val);
+
+ for (j = 0; j < lp->ncols; j++)
+ EGLPNUM_TYPENAME_EGlpNumZero (vA[j]);
+
+ for (i = 0; i < v->nzcnt; i++)
+ {
+ row = v->indx[i];
+ EGLPNUM_TYPENAME_EGlpNumCopy (val, v->coef[i]);
+ rcnt = lp->rowcnt[row];
+ rbeg = lp->rowbeg[row];
+ for (j = 0; j < rcnt; j++)
+ {
+ col = lp->rowind[rbeg + j];
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (vA[col], val, lp->rowval[rbeg + j]);
+ }
+ }
+
+ for (j = 0; j < lp->ncols; j++)
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (vA[j], EGLPNUM_TYPENAME_SZERO_TOLER))
+ EGLPNUM_TYPENAME_EGlpNumZero (vA[j]);
+
+ EGLPNUM_TYPENAME_EGlpNumClearVar (val);
+ return;
+}
+
+/* update information */
+
+/*
+1) lvstat - new status of leaving var.
+*/
+void EGLPNUM_TYPENAME_ILLfct_update_basis_info (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int eindex,
+ int lindex,
+ int lvstat)
+{
+ int evar;
+ int lvar;
+
+ evar = lp->nbaz[eindex];
+
+ if (lindex >= 0)
+ { /* variable leaves basis */
+ lvar = lp->baz[lindex];
+ lp->vstat[evar] = STAT_BASIC;
+ lp->vstat[lvar] = lvstat;
+ lp->vindex[evar] = lindex;
+ lp->vindex[lvar] = eindex;
+ lp->baz[lindex] = evar;
+ lp->nbaz[eindex] = lvar;
+ (lp->basisid)++;
+ }
+ else
+ {
+ lp->vstat[evar] = (lp->vstat[evar] == STAT_LOWER) ? STAT_UPPER : STAT_LOWER;
+ }
+}
+
+void EGLPNUM_TYPENAME_ILLfct_update_xz (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPE tz,
+ int eindex,
+ int lindex)
+{
+ int i, evar, estat;
+
+ ILL_IFTRACE ("%s:%la:%d:%d:%d\n", __func__, EGLPNUM_TYPENAME_EGlpNumToLf (tz), eindex,
+ lindex, lp->yjz.nzcnt);
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (tz))
+ for (i = 0; i < lp->yjz.nzcnt; i++)
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (lp->xbz[lp->yjz.indx[i]], tz, lp->yjz.coef[i]);
+
+ if (lindex >= 0)
+ { /* variable leaves basis */
+ evar = lp->nbaz[eindex];
+ estat = lp->vstat[evar];
+ if (estat == STAT_LOWER)
+ EGLPNUM_TYPENAME_EGlpNumCopySum (lp->xbz[lindex], lp->lz[evar], tz);
+ else if (estat == STAT_UPPER)
+ EGLPNUM_TYPENAME_EGlpNumCopySum (lp->xbz[lindex], lp->uz[evar], tz);
+ else if (estat == STAT_ZERO)
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->xbz[lindex], tz);
+ }
+}
+
+void EGLPNUM_TYPENAME_ILLfct_update_piz (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPE alpha)
+{
+ int i;
+
+ for (i = 0; i < lp->zz.nzcnt; i++)
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (lp->piz[lp->zz.indx[i]], alpha, lp->zz.coef[i]);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_update_pIpiz (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * z,
+ const EGLPNUM_TYPE alpha)
+{
+ int i;
+
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (alpha))
+ return;
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (alpha, EGLPNUM_TYPENAME_oneLpNum))
+ {
+ for (i = 0; i < z->nzcnt; i++)
+ EGLPNUM_TYPENAME_EGlpNumAddTo (lp->pIpiz[z->indx[i]], z->coef[i]);
+ }
+ else
+ {
+ for (i = 0; i < z->nzcnt; i++)
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (lp->pIpiz[z->indx[i]], alpha, z->coef[i]);
+ }
+}
+
+void EGLPNUM_TYPENAME_ILLfct_update_dz (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int eindex,
+ EGLPNUM_TYPE alpha)
+{
+ int i;
+
+ for (i = 0; i < lp->zA.nzcnt; i++)
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (lp->dz[lp->zA.indx[i]], alpha, lp->zA.coef[i]);
+ EGLPNUM_TYPENAME_EGlpNumCopyNeg (lp->dz[eindex], alpha);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_update_pIdz (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * zA,
+ int eindex,
+ const EGLPNUM_TYPE alpha)
+{
+ int i;
+
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (alpha))
+ return;
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (alpha, EGLPNUM_TYPENAME_oneLpNum))
+ {
+ for (i = 0; i < zA->nzcnt; i++)
+ EGLPNUM_TYPENAME_EGlpNumSubTo (lp->pIdz[zA->indx[i]], zA->coef[i]);
+ }
+ else
+ {
+ for (i = 0; i < zA->nzcnt; i++)
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (lp->pIdz[zA->indx[i]], alpha, zA->coef[i]);
+ }
+ if (eindex > -1)
+ EGLPNUM_TYPENAME_EGlpNumCopyNeg (lp->pIdz[eindex], alpha);
+}
+
+/* bound and coef shift routines */
+
+/* scale bound in my_rand to get more random digits, unless bound is large */
+static double my_rand (
+ int bound,
+ ILLrandstate * r)
+{
+ int k = bound, scale = 1;
+ double v = 0.0;
+
+ if (bound < 100000)
+ {
+ k = 20000 * bound;
+ scale = 20000;
+ }
+ v = 1 + (ILLutil_lprand (r) % (k));
+ return v / (double) scale;
+}
+
+static int expand_var_bounds (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPE ftol,
+ int *chgb)
+{
+ int rval = 0;
+ int i, col, nchg = 0;
+ EGLPNUM_TYPE newb, cftol;
+ EGLPNUM_TYPE *x, *l, *u;
+ ILLrandstate r;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (newb);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (cftol);
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs (cftol, ftol);
+ EGLPNUM_TYPENAME_EGlpNumDivUiTo (cftol, 10);
+
+ ILLutil_sprand (1, &r);
+
+ for (i = 0; i < lp->nrows; i++)
+ {
+ col = lp->baz[i];
+ if (lp->vtype[col] == VARTIFICIAL || lp->vtype[col] == VFREE)
+ continue;
+ x = &(lp->xbz[i]);
+ l = &(lp->lz[col]);
+ u = &(lp->uz[col]);
+ /* we use newb as temporal variable outside the if's scope */
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (newb, *x, ftol);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*l, EGLPNUM_TYPENAME_NINFTY) && EGLPNUM_TYPENAME_EGlpNumIsLess (newb, *l))
+ {
+ EGLPNUM_TYPENAME_EGlpNumSet (newb, -1.0 * (my_rand (50, &(lp->rstate)) + 1.0));
+ EGLPNUM_TYPENAME_EGlpNumMultTo (newb, cftol);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (*x, *l))
+ EGLPNUM_TYPENAME_EGlpNumAddTo (newb, *x);
+ else
+ EGLPNUM_TYPENAME_EGlpNumAddTo (newb, *l);
+ rval = EGLPNUM_TYPENAME_ILLfct_bound_shift (lp, col, BOUND_LOWER, newb);
+ CHECKRVALG (rval, CLEANUP);
+ nchg++;
+ }
+ EGLPNUM_TYPENAME_EGlpNumCopySum (newb, *x, ftol);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*u, EGLPNUM_TYPENAME_INFTY) && EGLPNUM_TYPENAME_EGlpNumIsLess (*u, newb))
+ {
+ EGLPNUM_TYPENAME_EGlpNumSet (newb, my_rand (50, &(lp->rstate)) + 1.0);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (newb, cftol);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (*x, *u))
+ EGLPNUM_TYPENAME_EGlpNumAddTo (newb, *u);
+ else
+ EGLPNUM_TYPENAME_EGlpNumAddTo (newb, *x);
+ rval = EGLPNUM_TYPENAME_ILLfct_bound_shift (lp, col, BOUND_UPPER, newb);
+ CHECKRVALG (rval, CLEANUP);
+ nchg++;
+ }
+ }
+ *chgb = nchg;
+
+CLEANUP:
+ EGLPNUM_TYPENAME_EGlpNumClearVar (newb);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (cftol);
+ EG_RETURN (rval);
+}
+
+static int expand_phaseI_bounds (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int *chgb)
+{
+ int rval = 0;
+ int i, col, nchg = 0;
+ EGLPNUM_TYPE newb, cftol;
+ EGLPNUM_TYPE *u, *l, *x;
+ ILLrandstate r;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (newb);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (cftol);
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs (cftol, lp->tol->ip_tol);
+ EGLPNUM_TYPENAME_EGlpNumDivUiTo (cftol, 10);
+ ILLutil_sprand (1, &r);
+
+ for (i = 0; i < lp->nrows; i++)
+ {
+ col = lp->baz[i];
+ if (lp->vtype[col] == VARTIFICIAL || lp->vtype[col] == VFREE)
+ continue;
+ x = &(lp->xbz[i]);
+ l = &(lp->lz[col]);
+ u = &(lp->uz[col]);
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*l, EGLPNUM_TYPENAME_NINFTY) && EGLPNUM_TYPENAME_EGlpNumIsEqual (*x, *l, cftol))
+ {
+ EGLPNUM_TYPENAME_EGlpNumSet (newb, my_rand (50, &(lp->rstate)) + 1.0);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (newb, cftol);
+ EGLPNUM_TYPENAME_EGlpNumSign (newb);
+ EGLPNUM_TYPENAME_EGlpNumAddTo (newb, *l);
+ rval = EGLPNUM_TYPENAME_ILLfct_bound_shift (lp, col, BOUND_LOWER, newb);
+ CHECKRVALG (rval, CLEANUP);
+ nchg++;
+ }
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*u, EGLPNUM_TYPENAME_INFTY) && EGLPNUM_TYPENAME_EGlpNumIsEqual (*x, *u, cftol))
+ {
+ EGLPNUM_TYPENAME_EGlpNumSet (newb, my_rand (50, &(lp->rstate)) + 1.0);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (newb, cftol);
+ EGLPNUM_TYPENAME_EGlpNumAddTo (newb, *u);
+ rval = EGLPNUM_TYPENAME_ILLfct_bound_shift (lp, col, BOUND_UPPER, newb);
+ CHECKRVALG (rval, CLEANUP);
+ nchg++;
+ }
+ }
+ *chgb = nchg;
+
+CLEANUP:
+ EGLPNUM_TYPENAME_EGlpNumClearVar (newb);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (cftol);
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLfct_adjust_viol_bounds (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ int rval = 0;
+ int chgb = 0;
+ EGLPNUM_TYPE tol;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (tol);
+ EGLPNUM_TYPENAME_EGlpNumCopyNeg (tol, lp->tol->pfeas_tol);
+ rval = expand_var_bounds (lp, tol, &chgb);
+#if FCT_DEBUG > 0
+ if (rval == 0)
+ QSlog("adjusting %d bounds", chgb);
+#endif
+ EGLPNUM_TYPENAME_EGlpNumClearVar (tol);
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLfct_perturb_bounds (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ int rval = 0;
+ int chgb = 0;
+
+ rval = expand_var_bounds (lp, lp->tol->ip_tol, &chgb);
+#if FCT_DEBUG > 0
+ if (rval == 0)
+ QSlog("perturbing %d bounds", chgb);
+#endif
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLfct_perturb_phaseI_bounds (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ int rval = 0;
+ int chgb = 0;
+
+ rval = expand_phaseI_bounds (lp, &chgb);
+#if FCT_DEBUG > 0
+ if (rval == 0)
+ QSlog("perturbing %d phase I bounds", chgb);
+#endif
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLfct_bound_shift (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int col,
+ int bndtype,
+ EGLPNUM_TYPE newbnd)
+{
+ int rval = 0;
+ EGLPNUM_TYPENAME_bndinfo *nbnd = 0;
+
+ ILL_IFTRACE ("\n%s:%d:%d:%la", __func__, col, bndtype, EGLPNUM_TYPENAME_EGlpNumToLf (newbnd));
+ nbnd = EGLPNUM_TYPENAME_ILLfct_new_bndinfo ();
+
+ nbnd->varnum = col;
+ nbnd->btype = bndtype;
+ if (bndtype == BOUND_LOWER)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (nbnd->pbound, lp->lz[col]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (nbnd->cbound, newbnd);
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->lz[col], newbnd);
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (nbnd->pbound, lp->uz[col]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (nbnd->cbound, newbnd);
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->uz[col], newbnd);
+ }
+ ILL_IFTRACE (":%la", EGLPNUM_TYPENAME_EGlpNumToLf (nbnd->pbound));
+ if (lp->vtype[col] == VFIXED || lp->vtype[col] == VARTIFICIAL)
+ {
+ /* QSlog("changing f/a bound"); */
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (lp->lz[col], lp->uz[col]))
+ lp->vtype[col] = VBOUNDED;
+ }
+
+ nbnd->next = lp->bchanges;
+ lp->bchanges = nbnd;
+ lp->nbchange++;
+
+//CLEANUP:
+ if (rval)
+ EGLPNUM_TYPENAME_ILLfct_free_bndinfo (nbnd);
+ ILL_IFTRACE ("\n");
+ EG_RETURN (rval);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_unroll_bound_change (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ int col;
+ int changex = 0;
+ EGLPNUM_TYPENAME_bndinfo *bptr = lp->bchanges;
+ EGLPNUM_TYPENAME_bndinfo *nptr = 0;
+
+ ILL_IFTRACE ("%s:", __func__);
+
+ while (lp->nbchange != 0)
+ {
+ col = bptr->varnum;
+ ILL_IFTRACE (":%d", col);
+
+ if (bptr->btype == BOUND_UPPER)
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->uz[col], bptr->pbound);
+ else
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->lz[col], bptr->pbound);
+
+ if (lp->vtype[col] == VBOUNDED)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (lp->lz[col], lp->uz[col]))
+ lp->vtype[col] = (!EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (lp->lz[col])) ?
+ VARTIFICIAL : VFIXED;
+ }
+
+ if (lp->vstat[col] != STAT_BASIC)
+ {
+ if ((bptr->btype == BOUND_UPPER && lp->vstat[col] == STAT_UPPER) ||
+ (bptr->btype == BOUND_LOWER && lp->vstat[col] == STAT_LOWER))
+ changex++;
+ }
+ nptr = bptr->next;
+ EGLPNUM_TYPENAME_EGlpNumClearVar ((bptr->cbound));
+ EGLPNUM_TYPENAME_EGlpNumClearVar ((bptr->pbound));
+ ILL_IFFREE (bptr, EGLPNUM_TYPENAME_bndinfo);
+ bptr = nptr;
+ lp->nbchange--;
+ }
+ lp->bchanges = bptr;
+ ILL_IFTRACE ("\n");
+ if (changex)
+ EGLPNUM_TYPENAME_ILLfct_compute_xbz (lp);
+}
+
+static int expand_var_coefs (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPE ftol,
+ int *chgc)
+{
+ int rval = 0;
+ int i, col, vs, vt;
+ int nchg = 0;
+ EGLPNUM_TYPE newc, cftol, mftol[1];
+ EGLPNUM_TYPE *c, *dj;
+ ILLrandstate r;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (newc);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (cftol);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (mftol[0]);
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs (cftol, ftol);
+ EGLPNUM_TYPENAME_EGlpNumDivUiTo (cftol, 10);
+ EGLPNUM_TYPENAME_EGlpNumCopyNeg (mftol[0], ftol);
+ ILLutil_sprand (1, &r);
+
+ for (i = 0; i < lp->nnbasic; i++)
+ {
+ dj = &(lp->dz[i]);
+ col = lp->nbaz[i];
+ c = &(lp->cz[col]);
+ vs = lp->vstat[col];
+ vt = lp->vtype[col];
+
+ if (vt == VARTIFICIAL || vt == VFIXED)
+ continue;
+ switch (vs)
+ {
+ case STAT_ZERO:
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (newc, *c, *dj);
+ rval = EGLPNUM_TYPENAME_ILLfct_coef_shift (lp, col, newc);
+ CHECKRVALG (rval, CLEANUP);
+ nchg++;
+ break;
+ case STAT_LOWER:
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (*dj, ftol))
+ {
+ EGLPNUM_TYPENAME_EGlpNumSet (newc, my_rand (50, &(lp->rstate)) + 1.0);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (newc, cftol);
+ EGLPNUM_TYPENAME_EGlpNumAddTo (newc, *c);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (*dj))
+ EGLPNUM_TYPENAME_EGlpNumSubTo (newc, *dj);
+ rval = EGLPNUM_TYPENAME_ILLfct_coef_shift (lp, col, newc);
+ CHECKRVALG (rval, CLEANUP);
+ nchg++;
+ }
+ break;
+ case STAT_UPPER:
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (mftol[0], *dj))
+ {
+ EGLPNUM_TYPENAME_EGlpNumSet (newc, my_rand (50, &(lp->rstate)) + 1.0);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (newc, cftol);
+ EGLPNUM_TYPENAME_EGlpNumSign (newc);
+ EGLPNUM_TYPENAME_EGlpNumAddTo (newc, *c);
+ if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (*dj))
+ EGLPNUM_TYPENAME_EGlpNumSubTo (newc, *dj);
+ rval = EGLPNUM_TYPENAME_ILLfct_coef_shift (lp, col, newc);
+ CHECKRVALG (rval, CLEANUP);
+ nchg++;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ *chgc = nchg;
+
+CLEANUP:
+ EGLPNUM_TYPENAME_EGlpNumClearVar (mftol[0]);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (newc);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (cftol);
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLfct_adjust_viol_coefs (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ int rval = 0;
+ int chgc = 0;
+ EGLPNUM_TYPE tol;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (tol);
+ EGLPNUM_TYPENAME_EGlpNumCopyNeg (tol, lp->tol->dfeas_tol);
+
+ rval = expand_var_coefs (lp, tol, &chgc);
+#if FCT_DEBUG > 0
+ if (rval == 0)
+ QSlog("perturbing %d coefs", chgc);
+#endif
+ EGLPNUM_TYPENAME_EGlpNumClearVar (tol);
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLfct_perturb_coefs (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ int rval = 0;
+ int chgc = 0;
+
+ rval = expand_var_coefs (lp, lp->tol->id_tol, &chgc);
+#if FCT_DEBUG > 0
+ if (rval == 0)
+ QSlog("perturbing %d coefs", chgc);
+#endif
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLfct_coef_shift (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int col,
+ EGLPNUM_TYPE newcoef)
+{
+ int rval = 0;
+ EGLPNUM_TYPENAME_coefinfo *ncoef = 0;
+
+ ILL_SAFE_MALLOC (ncoef, 1, EGLPNUM_TYPENAME_coefinfo);
+ EGLPNUM_TYPENAME_EGlpNumInitVar ((ncoef->pcoef));
+ EGLPNUM_TYPENAME_EGlpNumInitVar ((ncoef->ccoef));
+
+ ncoef->varnum = col;
+ EGLPNUM_TYPENAME_EGlpNumCopy (ncoef->pcoef, lp->cz[col]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (ncoef->ccoef, newcoef);
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->cz[col], newcoef);
+ ncoef->next = lp->cchanges;
+ lp->cchanges = ncoef;
+ EGLPNUM_TYPENAME_EGlpNumAddTo (lp->dz[lp->vindex[col]], ncoef->ccoef);
+ EGLPNUM_TYPENAME_EGlpNumSubTo (lp->dz[lp->vindex[col]], ncoef->pcoef);
+ lp->ncchange++;
+
+CLEANUP:
+ if (rval)
+ {
+ EGLPNUM_TYPENAME_EGlpNumClearVar ((ncoef->pcoef));
+ EGLPNUM_TYPENAME_EGlpNumClearVar ((ncoef->ccoef));
+ ILL_IFFREE (ncoef, EGLPNUM_TYPENAME_coefinfo);
+ }
+ EG_RETURN (rval);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_unroll_coef_change (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ int bascoef = 0;
+ EGLPNUM_TYPENAME_coefinfo *cptr = (EGLPNUM_TYPENAME_coefinfo *) lp->cchanges;
+ EGLPNUM_TYPENAME_coefinfo *nptr = 0;
+
+ while (lp->ncchange != 0)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->cz[cptr->varnum], cptr->pcoef);
+ if (lp->vstat[cptr->varnum] != STAT_BASIC)
+ {
+ EGLPNUM_TYPENAME_EGlpNumAddTo (lp->dz[lp->vindex[cptr->varnum]], cptr->pcoef);
+ EGLPNUM_TYPENAME_EGlpNumSubTo (lp->dz[lp->vindex[cptr->varnum]], cptr->ccoef);
+ }
+ else
+ bascoef++;
+
+ nptr = cptr->next;
+ EGLPNUM_TYPENAME_EGlpNumClearVar ((cptr->pcoef));
+ EGLPNUM_TYPENAME_EGlpNumClearVar ((cptr->ccoef));
+ ILL_IFFREE (cptr, EGLPNUM_TYPENAME_coefinfo);
+ cptr = nptr;
+ lp->ncchange--;
+ }
+ lp->cchanges = cptr;
+ if (bascoef)
+ {
+ EGLPNUM_TYPENAME_ILLfct_compute_piz (lp);
+ EGLPNUM_TYPENAME_ILLfct_compute_dz (lp);
+ }
+}
+
+/* feasibility routines */
+void EGLPNUM_TYPENAME_ILLfct_check_pfeasible (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_feas_info * fs,
+ const EGLPNUM_TYPE ftol)
+{
+ int i, col;
+ EGLPNUM_TYPE infeas, err1, err2;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (infeas);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (err1);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (err2);
+ EGLPNUM_TYPENAME_EGlpNumZero (infeas);
+ fs->pstatus = PRIMAL_FEASIBLE;
+ EGLPNUM_TYPENAME_EGlpNumZero (fs->totinfeas);
+ ILL_IFTRACE ("%s:tol %la\n", __func__, EGLPNUM_TYPENAME_EGlpNumToLf (ftol));
+
+ for (i = 0; i < lp->nrows; i++)
+ {
+ col = lp->baz[i];
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (err1, lp->xbz[i], lp->uz[col]);
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (err2, lp->lz[col], lp->xbz[i]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (ftol, err1)
+ && EGLPNUM_TYPENAME_EGlpNumIsNeq (lp->uz[col], EGLPNUM_TYPENAME_INFTY, EGLPNUM_TYPENAME_oneLpNum))
+ {
+ EGLPNUM_TYPENAME_EGlpNumAddTo (infeas, err1);
+ WARNINGL (QSE_WLVL, EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_INFTY, err1),
+ "This is imposible lu = %15lg xbz = %15lg" " EGLPNUM_TYPENAME_INFTY = %15lg",
+ EGLPNUM_TYPENAME_EGlpNumToLf (lp->uz[col]), EGLPNUM_TYPENAME_EGlpNumToLf (lp->xbz[i]),
+ EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_INFTY));
+ lp->bfeas[i] = 1;
+ }
+ else if (EGLPNUM_TYPENAME_EGlpNumIsLess (ftol, err2)
+ && EGLPNUM_TYPENAME_EGlpNumIsNeq (lp->lz[col], EGLPNUM_TYPENAME_NINFTY, EGLPNUM_TYPENAME_oneLpNum))
+ {
+ EGLPNUM_TYPENAME_EGlpNumAddTo (infeas, err2);
+ WARNINGL (QSE_WLVL, EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_INFTY, err2),
+ "This is imposible lz = %15lg xbz = %15lg" " EGLPNUM_TYPENAME_NINFTY = %15lg",
+ EGLPNUM_TYPENAME_EGlpNumToLf (lp->lz[col]), EGLPNUM_TYPENAME_EGlpNumToLf (lp->xbz[i]),
+ EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_NINFTY));
+ lp->bfeas[i] = -1;
+ }
+ else
+ lp->bfeas[i] = 0;
+ }
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (infeas))
+ {
+ fs->pstatus = PRIMAL_INFEASIBLE;
+ EGLPNUM_TYPENAME_EGlpNumCopy (fs->totinfeas, infeas);
+ ILL_IFTRACE ("%s:inf %la\n", __func__, EGLPNUM_TYPENAME_EGlpNumToLf (infeas));
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (fs->totinfeas))
+ {
+ QSlog("Negative infeasibility, Imposible! %lf %la",
+ EGLPNUM_TYPENAME_EGlpNumToLf (infeas), EGLPNUM_TYPENAME_EGlpNumToLf (infeas));
+ }
+ }
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->pinfeas, infeas);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (infeas);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (err1);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (err2);
+}
+
+/* feasibility routines */
+void EGLPNUM_TYPENAME_ILLfct_check_pIpfeasible (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_feas_info * fs,
+ EGLPNUM_TYPE ftol)
+{
+ int i, col;
+ int ninf = 0;
+
+ fs->pstatus = PRIMAL_FEASIBLE;
+ EGLPNUM_TYPENAME_EGlpNumZero (fs->totinfeas);
+
+ for (i = 0; i < lp->nrows; i++)
+ {
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (lp->xbz[i], ftol))
+ continue;
+ col = lp->baz[i];
+ if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero(lp->xbz[i]) &&
+ EGLPNUM_TYPENAME_EGlpNumIsNeqq (lp->uz[col], EGLPNUM_TYPENAME_INFTY))
+ {
+ ninf++;
+ }
+ else if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (lp->xbz[i]) &&
+ EGLPNUM_TYPENAME_EGlpNumIsNeqq (lp->lz[col], EGLPNUM_TYPENAME_NINFTY))
+ {
+ ninf++;
+ }
+ }
+ if (ninf != 0)
+ fs->pstatus = PRIMAL_INFEASIBLE;
+}
+
+void EGLPNUM_TYPENAME_ILLfct_check_dfeasible (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_feas_info * fs,
+ const EGLPNUM_TYPE ftol)
+{
+ int j, col;
+ EGLPNUM_TYPE infeas;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (infeas);
+ EGLPNUM_TYPENAME_EGlpNumZero (infeas);
+ fs->dstatus = DUAL_FEASIBLE;
+ EGLPNUM_TYPENAME_EGlpNumZero (fs->totinfeas);
+
+ for (j = 0; j < lp->nnbasic; j++)
+ {
+ lp->dfeas[j] = 0;
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (lp->dz[j], ftol))
+ continue;
+ col = lp->nbaz[j];
+
+ if (lp->vtype[col] == VARTIFICIAL || lp->vtype[col] == VFIXED)
+ continue;
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (lp->dz[j]) &&
+ (lp->vstat[col] == STAT_LOWER || lp->vstat[col] == STAT_ZERO))
+ {
+ EGLPNUM_TYPENAME_EGlpNumSubTo (infeas, lp->dz[j]);
+ lp->dfeas[j] = -1;
+ }
+ else if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (lp->dz[j]) &&
+ (lp->vstat[col] == STAT_UPPER || lp->vstat[col] == STAT_ZERO))
+ {
+ EGLPNUM_TYPENAME_EGlpNumAddTo (infeas, lp->dz[j]);
+ lp->dfeas[j] = 1;
+ }
+ }
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (infeas))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (fs->totinfeas, infeas);
+ fs->dstatus = DUAL_INFEASIBLE;
+ ILL_IFTRACE ("%s:inf %la\n", __func__, EGLPNUM_TYPENAME_EGlpNumToLf (infeas));
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (fs->totinfeas))
+ {
+ QSlog("Negative infeasibility, Imposible! %lf %la",
+ EGLPNUM_TYPENAME_EGlpNumToLf (infeas), EGLPNUM_TYPENAME_EGlpNumToLf (infeas));
+ }
+ }
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->dinfeas, infeas);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (infeas);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_check_pIdfeasible (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_feas_info * fs,
+ EGLPNUM_TYPE ftol)
+{
+ int j, col;
+ int ninf = 0;
+ EGLPNUM_TYPE *dz = lp->pIdz;
+
+ fs->dstatus = DUAL_FEASIBLE;
+
+ for (j = 0; j < lp->nnbasic; j++)
+ {
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (dz[j], ftol))
+ continue;
+ col = lp->nbaz[j];
+ if (lp->vtype[col] == VARTIFICIAL || lp->vtype[col] == VFIXED)
+ continue;
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (dz[j]) &&
+ (lp->vstat[col] == STAT_LOWER || lp->vstat[col] == STAT_ZERO))
+ ninf++;
+ else if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (dz[j]) &&
+ (lp->vstat[col] == STAT_UPPER || lp->vstat[col] == STAT_ZERO))
+ ninf++;
+ }
+
+ if (ninf != 0)
+ fs->dstatus = DUAL_INFEASIBLE;
+}
+
+void EGLPNUM_TYPENAME_ILLfct_dual_adjust (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ const EGLPNUM_TYPE ftol)
+{
+ int j, col;
+
+ for (j = 0; j < lp->nnbasic; j++)
+ {
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (lp->dz[j], ftol))
+ continue;
+ col = lp->nbaz[j];
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (lp->dz[j]) &&
+ EGLPNUM_TYPENAME_EGlpNumIsNeqq (lp->uz[col], EGLPNUM_TYPENAME_INFTY))
+ lp->vstat[col] = STAT_UPPER;
+ else if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (lp->dz[j]) &&
+ EGLPNUM_TYPENAME_EGlpNumIsNeqq (lp->lz[col], EGLPNUM_TYPENAME_NINFTY))
+ lp->vstat[col] = STAT_LOWER;
+ }
+}
+
+void EGLPNUM_TYPENAME_ILLfct_dphaseI_simple_update (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPE ftol)
+{
+ int j, col;
+
+ for (j = 0; j < lp->nnbasic; j++)
+ {
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (lp->dz[j], ftol))
+ continue;
+ col = lp->nbaz[j];
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (lp->dz[j] ) && lp->vtype[col] == VBOUNDED)
+ lp->vstat[col] = STAT_UPPER;
+ else if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (lp->dz[j]) && lp->vtype[col] == VBOUNDED)
+ lp->vstat[col] = STAT_LOWER;
+ }
+}
+
+/* set status values */
+void EGLPNUM_TYPENAME_ILLfct_set_status_values (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int pstatus,
+ int dstatus,
+ int ptype,
+ int dtype)
+{
+ if (dstatus == DUAL_FEASIBLE && dtype == PHASEII)
+ {
+ if (!lp->ncchange)
+ {
+ lp->probstat.dual_feasible = 1;
+ lp->basisstat.dual_feasible = 1;
+ lp->basisstat.dual_infeasible = 0;
+ }
+ }
+ if (dstatus == DUAL_INFEASIBLE && dtype == PHASEII)
+ {
+ if (!lp->ncchange)
+ {
+ lp->basisstat.dual_feasible = 0;
+ lp->basisstat.dual_infeasible = 1;
+ }
+ if (pstatus == PRIMAL_FEASIBLE && ptype == PHASEI)
+ if (!lp->ncchange)
+ lp->probstat.dual_infeasible = 1;
+ }
+ if (pstatus == PRIMAL_FEASIBLE && ptype == PHASEII)
+ {
+ if (!lp->nbchange)
+ {
+ lp->probstat.primal_feasible = 1;
+ lp->basisstat.primal_feasible = 1;
+ lp->basisstat.primal_infeasible = 0;
+ }
+ }
+ if (pstatus == PRIMAL_INFEASIBLE && ptype == PHASEII)
+ {
+ lp->basisstat.primal_feasible = 0;
+ lp->basisstat.primal_infeasible = 1;
+
+ if (dstatus == DUAL_FEASIBLE && dtype == PHASEI)
+ lp->probstat.primal_infeasible = 1;
+ }
+ if (pstatus == PRIMAL_UNBOUNDED)
+ {
+ if (!lp->nbchange)
+ {
+ lp->probstat.primal_unbounded = 1;
+ lp->basisstat.primal_unbounded = 1;
+ lp->probstat.dual_infeasible = 1;
+ lp->basisstat.dual_infeasible = 1;
+ lp->basisstat.dual_feasible = 0;
+ }
+ }
+ if (dstatus == DUAL_UNBOUNDED)
+ {
+ if (!lp->ncchange)
+ {
+ lp->probstat.dual_unbounded = 1;
+ lp->basisstat.dual_unbounded = 1;
+ lp->probstat.primal_infeasible = 1;
+ lp->basisstat.primal_infeasible = 1;
+ lp->basisstat.primal_feasible = 0;
+ }
+ }
+ if (lp->probstat.primal_feasible && lp->probstat.dual_feasible)
+ lp->probstat.optimal = 1;
+
+ if (lp->basisstat.primal_feasible && lp->basisstat.dual_feasible)
+ lp->basisstat.optimal = 1;
+ else
+ lp->basisstat.optimal = 0;
+}
+
+void EGLPNUM_TYPENAME_ILLfct_init_counts (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ int i;
+ EGLPNUM_TYPENAME_count_struct *c = lp->cnts;
+
+#define C_VALUE(a) (1.0+(double)(a)/(PARAM_HEAP_RATIO*ILLutil_our_log2(a)))
+ EGLPNUM_TYPENAME_EGlpNumSet (c->y_ravg, C_VALUE (lp->nrows));
+ EGLPNUM_TYPENAME_EGlpNumSet (c->za_ravg, C_VALUE (lp->nnbasic));
+ ILL_IFTRACE ("%s:%la\n", __func__, EGLPNUM_TYPENAME_EGlpNumToLf (c->za_ravg));
+#undef C_VALUE
+ c->ynz_cnt = 0;
+ c->num_y = 0;
+ c->znz_cnt = 0;
+ c->num_z = 0;
+ c->zanz_cnt = 0;
+ c->num_za = 0;
+ c->pnorm_cnt = 0;
+ c->dnorm_cnt = 0;
+ c->pinz_cnt = 0;
+ c->num_pi = 0;
+ c->pi1nz_cnt = 0;
+ c->num_pi1 = 0;
+ c->upnz_cnt = 0;
+ c->num_up = 0;
+ c->pupv_cnt = 0;
+ c->dupv_cnt = 0;
+ c->pI_iter = 0;
+ c->pII_iter = 0;
+ c->dI_iter = 0;
+ c->dII_iter = 0;
+ c->tot_iter = 0;
+ for (i = 0; i < 10; i++)
+ {
+ c->pivpI[i] = 0;
+ c->pivpII[i] = 0;
+ c->pivdI[i] = 0;
+ c->pivdII[i] = 0;
+ }
+}
+
+static void update_piv_values (
+ EGLPNUM_TYPENAME_count_struct * c,
+ int phase,
+ const EGLPNUM_TYPE piv2)
+{
+ int i = 0;
+ EGLPNUM_TYPE v, piv;
+
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqqZero(piv2))
+ return;
+ EGLPNUM_TYPENAME_EGlpNumInitVar (v);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (piv);
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs (piv, piv2);
+ EGLPNUM_TYPENAME_EGlpNumOne (v);
+ while (EGLPNUM_TYPENAME_EGlpNumIsLess (piv, v) && i < 9)
+ {
+ EGLPNUM_TYPENAME_EGlpNumDivUiTo (v, 10);
+ i++;
+ }
+ switch (phase)
+ {
+ case PRIMAL_PHASEI:
+ c->pivpI[i]++;
+ break;
+ case PRIMAL_PHASEII:
+ c->pivpII[i]++;
+ break;
+ case DUAL_PHASEI:
+ c->pivdI[i]++;
+ break;
+ case DUAL_PHASEII:
+ c->pivdII[i]++;
+ break;
+ default:
+ break;
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (v);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (piv);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_update_counts (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int f,
+ int upi,
+ const EGLPNUM_TYPE upd)
+{
+ EGLPNUM_TYPENAME_count_struct *c = lp->cnts;
+
+ switch (f)
+ {
+ case CNT_PPHASE1ITER:
+ c->pI_iter++;
+ c->tot_iter++;
+ break;
+ case CNT_PPHASE2ITER:
+ c->pII_iter++;
+ c->tot_iter++;
+ break;
+ case CNT_DPHASE1ITER:
+ c->dI_iter++;
+ c->tot_iter++;
+ break;
+ case CNT_DPHASE2ITER:
+ c->dII_iter++;
+ c->tot_iter++;
+ break;
+ case CNT_YNZ:
+ c->ynz_cnt += upi;
+ c->num_y++;
+ break;
+ case CNT_ZANZ:
+ c->zanz_cnt += upi;
+ c->num_za++;
+ break;
+ case CNT_PINZ:
+ c->pinz_cnt += upi;
+ c->num_pi++;
+ break;
+ case CNT_P1PINZ:
+ c->pi1nz_cnt += upi;
+ c->num_pi1++;
+ break;
+ case CNT_UPNZ:
+ c->upnz_cnt += upi;
+ c->num_up++;
+ break;
+ case CNT_PIPIV:
+ update_piv_values (c, PRIMAL_PHASEI, upd);
+ break;
+ case CNT_PIIPIV:
+ update_piv_values (c, PRIMAL_PHASEII, upd);
+ break;
+ case CNT_DIPIV:
+ update_piv_values (c, DUAL_PHASEI, upd);
+ break;
+ case CNT_DIIPIV:
+ update_piv_values (c, DUAL_PHASEII, upd);
+ break;
+ case CNT_YRAVG:
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (c->y_ravg, c->tot_iter);
+ EGLPNUM_TYPENAME_EGlpNumAddUiTo (c->y_ravg, upi);
+ EGLPNUM_TYPENAME_EGlpNumDivUiTo (c->y_ravg, c->tot_iter + 1);
+ break;
+ case CNT_ZARAVG:
+ ILL_IFTRACE ("%s:%d:%d:%d:%la:%la", __func__, f, c->tot_iter, upi,
+ EGLPNUM_TYPENAME_EGlpNumToLf (upd), EGLPNUM_TYPENAME_EGlpNumToLf (c->za_ravg));
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (c->za_ravg, c->tot_iter);
+ EGLPNUM_TYPENAME_EGlpNumAddUiTo (c->za_ravg, upi);
+ EGLPNUM_TYPENAME_EGlpNumDivUiTo (c->za_ravg, c->tot_iter + 1);
+ ILL_IFTRACE (":%la\n", EGLPNUM_TYPENAME_EGlpNumToLf (c->za_ravg));
+ break;
+ }
+}
+
+void EGLPNUM_TYPENAME_ILLfct_print_counts (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ int i, niter;
+ EGLPNUM_TYPENAME_count_struct *c = lp->cnts;
+
+ c->tot_iter = c->pI_iter + c->pII_iter + c->dI_iter + c->dII_iter;
+ niter = (c->tot_iter == 0) ? 1 : c->tot_iter;
+ QSlog("Counts for problem %s", lp->O->probname);
+ if (c->num_y != 0)
+ QSlog("avg ynz = %.2f", (double) c->ynz_cnt / c->num_y);
+ if (c->num_z != 0)
+ QSlog("avg znz = %.2f", (double) c->znz_cnt / c->num_z);
+ if (c->num_za != 0)
+ QSlog("avg zanz = %.2f", (double) c->zanz_cnt / c->num_za);
+ QSlog("avg pnorm = %.2f", (double) c->pnorm_cnt / lp->nnbasic);
+ QSlog("avg dnorm = %.2f", (double) c->dnorm_cnt / lp->nrows);
+ if (c->num_pi != 0)
+ QSlog("avg pinz = %.2f", (double) c->pinz_cnt / c->num_pi);
+ if (c->num_pi1 != 0)
+ QSlog("avg piInz = %.2f", (double) c->pi1nz_cnt / c->num_pi1);
+ if (c->num_up != 0)
+ QSlog("avg upnz = %.2f", (double) c->upnz_cnt / c->num_up);
+
+ for (i = 0; i < 10; i++)
+ QSlog("piv 1.0e-%d : %d %d %d %d",
+ i, c->pivpI[i], c->pivpII[i], c->pivdI[i], c->pivdII[i]);
+}
+
+
+/* c <- a + t*b */
+static void add_vectors (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * a,
+ EGLPNUM_TYPENAME_svector * b,
+ EGLPNUM_TYPENAME_svector * c,
+ const EGLPNUM_TYPE t)
+{
+ int i, r, l;
+ EGLPNUM_TYPENAME_svector *w = &(lp->work);
+
+ for (i = 0; i < b->nzcnt; i++)
+ {
+ r = b->indx[i];
+ w->indx[i] = r;
+ EGLPNUM_TYPENAME_EGlpNumCopy (w->coef[r], t);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (w->coef[r], b->coef[i]);
+ lp->iwork[r] = 1;
+ }
+ l = b->nzcnt;
+
+ for (i = 0; i < a->nzcnt; i++)
+ {
+ r = a->indx[i];
+ if (lp->iwork[r] == 0)
+ w->indx[l++] = r;
+ EGLPNUM_TYPENAME_EGlpNumAddTo (w->coef[r], a->coef[i]);
+ }
+ for (i = 0; i < l; i++)
+ {
+ r = w->indx[i];
+ c->indx[i] = r;
+ EGLPNUM_TYPENAME_EGlpNumCopy (c->coef[i], w->coef[r]);
+ EGLPNUM_TYPENAME_EGlpNumZero (w->coef[r]);
+ lp->iwork[r] = 0;
+ }
+ w->nzcnt = 0;
+ c->nzcnt = l;
+}
+
+void EGLPNUM_TYPENAME_ILLfct_update_pfeas (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int lindex,
+ EGLPNUM_TYPENAME_svector * srhs)
+{
+ int i, k, r;
+ int col, nz = 0;
+ int cbnd, f;
+ int *perm = lp->upd.perm;
+ int *ix = lp->upd.ix;
+ int tctr = lp->upd.tctr;
+ EGLPNUM_TYPE *t = lp->upd.t;
+ EGLPNUM_TYPE tz, *dty, ntmp;
+ EGLPNUM_TYPE *l, *x, *u, *pftol = &(lp->tol->ip_tol);
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (tz);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (ntmp);
+ dty = &(lp->upd.dty);
+ EGLPNUM_TYPENAME_EGlpNumZero (*dty);
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs (tz, lp->upd.tz);
+ EGLPNUM_TYPENAME_EGlpNumDivUiTo (tz, 100);
+ EGLPNUM_TYPENAME_EGlpNumAddTo (tz, lp->upd.tz);
+ ILL_IFTRACE ("%s:%d", __func__, tctr);
+ for (i = 0; i < tctr && EGLPNUM_TYPENAME_EGlpNumIsLeq (t[perm[i]], tz); i++)
+ {
+ cbnd = ix[perm[i]] % 10;
+ ILL_IFTRACE (":%d", cbnd);
+ if (cbnd == BBOUND)
+ continue;
+ k = ix[perm[i]] / 10;
+ r = lp->yjz.indx[k];
+ ILL_IFTRACE (":%d:%d:%d", k, r, lp->iwork[r]);
+
+ if (lp->iwork[r] != 1)
+ {
+ lp->iwork[r] = 1;
+ x = &(lp->xbz[r]);
+ col = lp->baz[r];
+ l = &(lp->lz[col]);
+ u = &(lp->uz[col]);
+
+ if (r != lindex)
+ {
+ f = 0;
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (ntmp, *l, *x);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*l, EGLPNUM_TYPENAME_NINFTY) && EGLPNUM_TYPENAME_EGlpNumIsLess (*pftol, ntmp))
+ f = -1;
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (ntmp, *x, *u);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*u, EGLPNUM_TYPENAME_INFTY) && EGLPNUM_TYPENAME_EGlpNumIsLess (*pftol, ntmp))
+ f = 1;
+ }
+
+ ILL_IFTRACE (":%d:%d", f, lp->bfeas[r]);
+ if (f != lp->bfeas[r])
+ {
+ srhs->indx[nz] = r;
+ EGLPNUM_TYPENAME_EGlpNumSet (srhs->coef[nz], (double) (f - lp->bfeas[r]));
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (*dty, srhs->coef[nz], lp->yjz.coef[k]);
+ nz++;
+ lp->bfeas[r] = f;
+ }
+ }
+ else
+ {
+ lp->bfeas[r] = 0;
+ }
+ }
+ }
+ while (--i >= 0)
+ {
+ cbnd = ix[perm[i]] % 10;
+ if (cbnd == BBOUND)
+ continue;
+ k = ix[perm[i]] / 10;
+ r = lp->yjz.indx[k];
+ lp->iwork[r] = 0;
+ }
+ srhs->nzcnt = nz;
+ ILL_IFTRACE (":%d\n", nz);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (tz);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_compute_ppIzz (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * srhs,
+ EGLPNUM_TYPENAME_svector * ssoln)
+{
+ if (srhs->nzcnt != 0)
+ {
+ ILL_IFTRACE ("%s:\n", __func__);
+ EGLPNUM_TYPENAME_ILLbasis_row_solve (lp, srhs, ssoln);
+ }
+}
+
+void EGLPNUM_TYPENAME_ILLfct_update_ppI_prices (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * pinf,
+ EGLPNUM_TYPENAME_svector * srhs,
+ EGLPNUM_TYPENAME_svector * ssoln,
+ int eindex,
+ int lindex,
+ const EGLPNUM_TYPE alpha)
+{
+ EGLPNUM_TYPE ntmp;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (ntmp);
+ EGLPNUM_TYPENAME_EGlpNumCopy (ntmp, alpha);
+ ILL_IFTRACE ("%s:\n", __func__);
+ if (lindex == -1)
+ {
+ if (srhs->nzcnt != 0)
+ {
+ EGLPNUM_TYPENAME_ILLfct_update_pIpiz (lp, ssoln, EGLPNUM_TYPENAME_oneLpNum);
+ if (pinf->p_strategy == COMPLETE_PRICING)
+ {
+ EGLPNUM_TYPENAME_ILLfct_compute_zA (lp, ssoln, &(lp->zA));
+ EGLPNUM_TYPENAME_ILLfct_update_pIdz (lp, &(lp->zA), -1, EGLPNUM_TYPENAME_oneLpNum);
+ }
+ }
+ else
+ {
+ if (pinf->p_strategy == COMPLETE_PRICING)
+ EGLPNUM_TYPENAME_ILLprice_compute_dual_inf (lp, pinf, &eindex, 1, PRIMAL_PHASEI);
+ else
+ EGLPNUM_TYPENAME_ILLprice_update_mpartial_price (lp, pinf, PRIMAL_PHASEI, COL_PRICING);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+ return;
+ }
+ }
+ else
+ {
+ if (srhs->nzcnt == 0)
+ {
+ EGLPNUM_TYPENAME_ILLfct_update_pIpiz (lp, &(lp->zz), ntmp);
+ if (pinf->p_strategy == COMPLETE_PRICING)
+ EGLPNUM_TYPENAME_ILLfct_update_pIdz (lp, &(lp->zA), eindex, ntmp);
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (ntmp, lp->upd.dty, lp->upd.piv);
+ EGLPNUM_TYPENAME_EGlpNumSubTo (ntmp, alpha);
+ EGLPNUM_TYPENAME_EGlpNumSign (ntmp);
+ add_vectors (lp, ssoln, &(lp->zz), &(lp->zz), ntmp);
+ EGLPNUM_TYPENAME_ILLfct_update_pIpiz (lp, &(lp->zz), EGLPNUM_TYPENAME_oneLpNum);
+ if (pinf->p_strategy == COMPLETE_PRICING)
+ {
+ EGLPNUM_TYPENAME_ILLfct_compute_zA (lp, &(lp->zz), &(lp->zA));
+ EGLPNUM_TYPENAME_ILLfct_update_pIdz (lp, &(lp->zA), eindex, EGLPNUM_TYPENAME_oneLpNum);
+ }
+ }
+ EGLPNUM_TYPENAME_EGlpNumSet (lp->pIdz[eindex], (double) (lp->upd.fs));
+ EGLPNUM_TYPENAME_EGlpNumAddTo (lp->pIdz[eindex], ntmp);
+ EGLPNUM_TYPENAME_EGlpNumSign (lp->pIdz[eindex]);
+ }
+ if (pinf->p_strategy == COMPLETE_PRICING)
+ {
+ EGLPNUM_TYPENAME_ILLprice_compute_dual_inf (lp, pinf, lp->zA.indx, lp->zA.nzcnt,
+ PRIMAL_PHASEI);
+ if (eindex > -1)
+ EGLPNUM_TYPENAME_ILLprice_compute_dual_inf (lp, pinf, &eindex, 1, PRIMAL_PHASEI);
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_ZARAVG, lp->zA.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+ }
+ else
+ EGLPNUM_TYPENAME_ILLprice_update_mpartial_price (lp, pinf, PRIMAL_PHASEI, COL_PRICING);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+ return;
+}
+
+void EGLPNUM_TYPENAME_ILLfct_update_dfeas (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int eindex,
+ EGLPNUM_TYPENAME_svector * srhs)
+{
+ int i, j, k, c;
+ int cbnd, col, nz = 0;
+ int vs, vt, f;
+ int delta;
+ int *perm = lp->upd.perm;
+ int *ix = lp->upd.ix;
+ int tctr = lp->upd.tctr;
+ int mcnt, mbeg;
+ EGLPNUM_TYPE *t = lp->upd.t;
+ EGLPNUM_TYPE *w = lp->work.coef;
+ EGLPNUM_TYPE tz;
+ EGLPNUM_TYPE *dty = &(lp->upd.dty);
+ EGLPNUM_TYPE *dftol = &(lp->tol->id_tol);
+ EGLPNUM_TYPE dj;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (dj);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (tz);
+ EGLPNUM_TYPENAME_EGlpNumZero (*dty);
+ EGLPNUM_TYPENAME_EGlpNumCopy (tz, lp->upd.tz);
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (tz, 101);
+ EGLPNUM_TYPENAME_EGlpNumDivUiTo (tz, 100);
+
+ for (j = 0; j < tctr && EGLPNUM_TYPENAME_EGlpNumIsLeq (t[perm[j]], tz); j++)
+ {
+ k = ix[perm[j]] / 10;
+ c = lp->zA.indx[k];
+
+ if (lp->iwork[c] != 1)
+ {
+ lp->iwork[c] = 1;
+ cbnd = ix[perm[j]] % 10;
+ col = lp->nbaz[c];
+ EGLPNUM_TYPENAME_EGlpNumCopy (dj, lp->dz[c]);
+ vs = lp->vstat[col];
+ vt = lp->vtype[col];
+
+ if (cbnd == BSKIP)
+ {
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (dj, *dftol));
+ else if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (dj) && vs == STAT_LOWER)
+ lp->vstat[col] = STAT_UPPER;
+ else if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (dj) && vs == STAT_UPPER)
+ lp->vstat[col] = STAT_LOWER;
+ }
+ else if (c != eindex)
+ {
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (dj, *dftol))
+ f = 0;
+ else if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (dj) &&
+ (vs == STAT_LOWER || vs == STAT_ZERO))
+ f = -1;
+ else if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (dj) &&
+ (vs == STAT_UPPER || vs == STAT_ZERO))
+ f = 1;
+ else
+ f = 0;
+
+ if (f != lp->dfeas[c])
+ {
+ delta = f - lp->dfeas[c];
+ mcnt = lp->matcnt[col];
+ mbeg = lp->matbeg[col];
+ EGLPNUM_TYPENAME_EGlpNumSet (dj, (double) (delta));
+ for (i = 0; i < mcnt; i++)
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (w[lp->matind[mbeg + i]], dj,
+ lp->matval[mbeg + i]);
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (*dty, dj, lp->zA.coef[k]);
+ nz = 1;
+ lp->dfeas[c] = f;
+ }
+ }
+ else
+ {
+ lp->dfeas[c] = 0;
+ }
+ }
+ }
+ while (--j >= 0)
+ {
+ k = ix[perm[j]] / 10;
+ c = lp->zA.indx[k];
+ lp->iwork[c] = 0;
+ }
+
+ if (nz)
+ {
+ for (i = 0, nz = 0; i < lp->nrows; i++)
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (w[i]))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (srhs->coef[nz], w[i]);
+ srhs->indx[nz] = i;
+ nz++;
+ EGLPNUM_TYPENAME_EGlpNumZero (w[i]);
+ }
+ }
+
+ srhs->nzcnt = nz;
+ EGLPNUM_TYPENAME_EGlpNumClearVar (dj);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (tz);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_compute_dpIy (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * srhs,
+ EGLPNUM_TYPENAME_svector * ssoln)
+{
+ if (srhs->nzcnt != 0)
+ {
+ EGLPNUM_TYPENAME_ILLbasis_column_solve (lp, srhs, ssoln);
+ }
+}
+
+void EGLPNUM_TYPENAME_ILLfct_update_dpI_prices (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * pinf,
+ EGLPNUM_TYPENAME_svector * srhs,
+ EGLPNUM_TYPENAME_svector * ssoln,
+ int lindex,
+ EGLPNUM_TYPE alpha)
+{
+ int i;
+ EGLPNUM_TYPE ntmp;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (ntmp);
+ EGLPNUM_TYPENAME_EGlpNumZero (ntmp);
+
+ if (srhs->nzcnt == 0)
+ {
+ EGLPNUM_TYPENAME_ILLfct_update_xz (lp, alpha, -1, -1);
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (ntmp, lp->upd.dty, lp->upd.piv);
+ EGLPNUM_TYPENAME_EGlpNumAddTo (ntmp, alpha);
+ EGLPNUM_TYPENAME_EGlpNumSign (ntmp);
+ add_vectors (lp, ssoln, &(lp->yjz), &(lp->yjz), ntmp);
+ EGLPNUM_TYPENAME_EGlpNumSign (ntmp);
+ for (i = 0; i < lp->yjz.nzcnt; i++)
+ EGLPNUM_TYPENAME_EGlpNumAddTo (lp->xbz[lp->yjz.indx[i]], lp->yjz.coef[i]);
+ }
+ EGLPNUM_TYPENAME_EGlpNumSet (lp->xbz[lindex], ((double) (-lp->upd.fs)));
+ EGLPNUM_TYPENAME_EGlpNumAddTo (lp->xbz[lindex], ntmp);
+
+ if (pinf->d_strategy == COMPLETE_PRICING)
+ {
+ EGLPNUM_TYPENAME_ILLprice_compute_primal_inf (lp, pinf, lp->yjz.indx, lp->yjz.nzcnt,
+ DUAL_PHASEI);
+ EGLPNUM_TYPENAME_ILLprice_compute_primal_inf (lp, pinf, &lindex, 1, DUAL_PHASEI);
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_YRAVG, lp->yjz.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+ }
+ else
+ EGLPNUM_TYPENAME_ILLprice_update_mpartial_price (lp, pinf, DUAL_PHASEI, ROW_PRICING);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_update_dIIfeas (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int eindex,
+ EGLPNUM_TYPENAME_svector * srhs)
+{
+ int j, k;
+ int col, indx, vs;
+ int *perm = lp->upd.perm;
+ int *ix = lp->upd.ix;
+ int tctr = lp->upd.tctr;
+ EGLPNUM_TYPE *zAj, *l, *u;
+ EGLPNUM_TYPE *dty = &(lp->upd.dty);
+ EGLPNUM_TYPE *t_max = &(lp->upd.tz);
+ EGLPNUM_TYPE *t = lp->upd.t;
+ EGLPNUM_TYPE delta;
+ EGLPNUM_TYPENAME_svector a;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (delta);
+ EGLPNUM_TYPENAME_EGlpNumZero (delta);
+ EGLPNUM_TYPENAME_EGlpNumZero (*dty);
+
+ srhs->nzcnt = 0;
+ for (j = 0; j < tctr && EGLPNUM_TYPENAME_EGlpNumIsLeq (t[perm[j]], *t_max); j++)
+ {
+ k = ix[perm[j]];
+ indx = lp->zA.indx[k];
+
+ if (indx != eindex)
+ {
+ zAj = &(lp->zA.coef[k]);
+ col = lp->nbaz[indx];
+ l = &(lp->lz[col]);
+ u = &(lp->uz[col]);
+ vs = lp->vstat[col];
+ if (vs == STAT_UPPER)
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (delta, *l, *u);
+ else
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (delta, *u, *l);
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (*dty, delta, *zAj);
+ lp->vstat[col] = (vs == STAT_UPPER) ? STAT_LOWER : STAT_UPPER;
+
+ a.nzcnt = lp->matcnt[col];
+ a.indx = &(lp->matind[lp->matbeg[col]]);
+ a.coef = &(lp->matval[lp->matbeg[col]]);
+ add_vectors (lp, srhs, &a, srhs, delta);
+ }
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (delta);
+}
+
+void EGLPNUM_TYPENAME_ILLfct_compute_dpIIy (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * srhs,
+ EGLPNUM_TYPENAME_svector * ssoln)
+{
+ if (srhs->nzcnt != 0)
+ {
+ EGLPNUM_TYPENAME_ILLbasis_column_solve (lp, srhs, ssoln);
+ }
+}
+
+void EGLPNUM_TYPENAME_ILLfct_update_dpII_prices (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * pinf,
+ EGLPNUM_TYPENAME_svector * srhs,
+ EGLPNUM_TYPENAME_svector * ssoln,
+ /*int eindex,*/
+ int lindex,
+ EGLPNUM_TYPE eval,
+ EGLPNUM_TYPE alpha)
+{
+ int i;
+ EGLPNUM_TYPENAME_svector *u;
+
+ if (srhs->nzcnt == 0)
+ {
+ EGLPNUM_TYPENAME_ILLfct_update_xz (lp, alpha, -1, -1);
+ u = &(lp->yjz);
+ }
+ else
+ {
+ if (ssoln->nzcnt != 0)
+ for (i = 0; i < ssoln->nzcnt; i++)
+ EGLPNUM_TYPENAME_EGlpNumSubTo (lp->xbz[ssoln->indx[i]], ssoln->coef[i]);
+ EGLPNUM_TYPENAME_ILLfct_update_xz (lp, alpha, -1, -1);
+ add_vectors (lp, ssoln, &(lp->yjz), ssoln, EGLPNUM_TYPENAME_oneLpNum);
+ u = ssoln;
+ }
+ EGLPNUM_TYPENAME_EGlpNumCopySum (lp->xbz[lindex], eval, alpha);
+
+ if (pinf->d_strategy == COMPLETE_PRICING)
+ {
+ EGLPNUM_TYPENAME_ILLprice_compute_primal_inf (lp, pinf, u->indx, u->nzcnt, DUAL_PHASEII);
+ EGLPNUM_TYPENAME_ILLprice_compute_primal_inf (lp, pinf, &lindex, 1, DUAL_PHASEII);
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_YRAVG, u->nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+ }
+ else
+ EGLPNUM_TYPENAME_ILLprice_update_mpartial_price (lp, pinf, DUAL_PHASEII, ROW_PRICING);
+}
+
+int EGLPNUM_TYPENAME_ILLfct_test_pivot (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int indx,
+ int indxtype,
+ EGLPNUM_TYPE piv_val)
+{
+ int i;
+ EGLPNUM_TYPE pval, ntmp;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (pval);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (ntmp);
+ EGLPNUM_TYPENAME_EGlpNumZero (pval);
+
+ if (indxtype == ROW_PIVOT)
+ {
+ for (i = 0; i < lp->yjz.nzcnt; i++)
+ if (lp->yjz.indx[i] == indx)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (pval, lp->yjz.coef[i]);
+ break;
+ }
+ }
+ else
+ {
+ for (i = 0; i < lp->zA.nzcnt; i++)
+ if (lp->zA.indx[i] == indx)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (pval, lp->zA.coef[i]);
+ break;
+ }
+ }
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (ntmp, pval, piv_val);
+ EGLPNUM_TYPENAME_EGlpNumDivTo (ntmp, piv_val);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (ntmp))
+ EGLPNUM_TYPENAME_EGlpNumSign (ntmp);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_ALTPIV_TOLER, ntmp))
+ {
+#if FCT_DEBUG > 1
+ if (indxtype == ROW_PIVOT)
+ QSlog("y_i = %.8f, z_j = %.8f %la %la", EGLPNUM_TYPENAME_EGlpNumToLf (pval),
+ EGLPNUM_TYPENAME_EGlpNumToLf (piv_val), EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_ALTPIV_TOLER),
+ EGLPNUM_TYPENAME_EGlpNumToLf (ntmp));
+ else
+ QSlog("z_j = %.8f, y_i = %.8f", EGLPNUM_TYPENAME_EGlpNumToLf (pval),
+ EGLPNUM_TYPENAME_EGlpNumToLf (piv_val));
+#endif
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (pval);
+ return 1;
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (pval);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+ return 0;
+}
+
+#if FCT_DEBUG > 0
+
+void EGLPNUM_TYPENAME_fct_test_workvector (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ int i, err = 0;
+
+ for (i = 0; i < lp->ncols; i++)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (lp->work.coef[i]))
+ {
+ err++;
+ EGLPNUM_TYPENAME_EGlpNumZero (lp->work.coef[i]);
+ }
+ if (lp->iwork[i] != 0)
+ {
+ err++;
+ lp->iwork[i] = 0;
+ }
+ }
+ if (err)
+ QSlog("bad work vector, err=%d", err);
+}
+
+void EGLPNUM_TYPENAME_fct_test_pfeasible (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ int i, col;
+ int err = 0;
+ EGLPNUM_TYPE *ftol = &(lp->tol->pfeas_tol);
+
+ for (i = 0; i < lp->nrows; i++)
+ {
+ col = lp->baz[i];
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (lp->uz[col], EGLPNUM_TYPENAME_INFTY)
+ && EGLPNUM_TYPENAME_EGlpNumIsSumLess (*ftol, lp->uz[col], lp->xbz[i]))
+ {
+ if (lp->bfeas[i] != 1)
+ {
+ err++;
+ lp->bfeas[i] = 1;
+ }
+ }
+ else if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (lp->lz[col], EGLPNUM_TYPENAME_NINFTY)
+ && EGLPNUM_TYPENAME_EGlpNumIsSumLess (lp->xbz[i], *ftol, lp->lz[col]))
+ {
+ if (lp->bfeas[i] != -1)
+ {
+ err++;
+ lp->bfeas[i] = -1;
+ }
+ }
+ /* else if (lp->bfeas[i] != 0) {err++; lp->bfeas[i] = 0;} */
+ }
+ if (err != 0)
+ QSlog("test_pfeas err =%d", err);
+}
+
+void EGLPNUM_TYPENAME_fct_test_dfeasible (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ int j, col;
+ int err = 0;
+ EGLPNUM_TYPE *ftol = &(lp->tol->dfeas_tol);
+ EGLPNUM_TYPE mftol[1];
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (mftol[0]);
+ EGLPNUM_TYPENAME_EGlpNumCopyNeg (mftol[0], *ftol);
+
+ for (j = 0; j < lp->nnbasic; j++)
+ {
+ col = lp->nbaz[j];
+
+ if (lp->vtype[col] == VARTIFICIAL || lp->vtype[col] == VFIXED)
+ continue;
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (lp->dz[j], mftol[0]) &&
+ (lp->vstat[col] == STAT_LOWER || lp->vstat[col] == STAT_ZERO))
+ {
+ if (lp->dfeas[j] != -1)
+ {
+ err++;
+ lp->dfeas[j] = -1;
+ }
+ }
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (*ftol, lp->dz[j]) &&
+ (lp->vstat[col] == STAT_UPPER || lp->vstat[col] == STAT_ZERO))
+ {
+ if (lp->dfeas[j] != 1)
+ {
+ err++;
+ lp->dfeas[j] = 1;
+ }
+ }
+ /* else if (lp->dfeas[j] != 0) {err++; lp->dfeas[j] = 0;} */
+ }
+ if (err != 0)
+ QSlog("test_dfeas err =%d", err);
+}
+
+void EGLPNUM_TYPENAME_fct_test_pI_x (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * p)
+{
+ int i;
+ int ern = 0;
+ EGLPNUM_TYPE *x;
+ EGLPNUM_TYPE err, diff;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (err);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (diff);
+ EGLPNUM_TYPENAME_EGlpNumZero (err);
+ x = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+
+ for (i = 0; i < lp->nrows; i++)
+ EGLPNUM_TYPENAME_EGlpNumCopy (x[i], lp->xbz[i]);
+ EGLPNUM_TYPENAME_ILLfct_compute_phaseI_xbz (lp);
+ for (i = 0; i < lp->nrows; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (diff, x[i], lp->xbz[i]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (diff))
+ EGLPNUM_TYPENAME_EGlpNumSign (diff);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_PFEAS_TOLER, diff))
+ {
+ EGLPNUM_TYPENAME_EGlpNumAddTo (err, diff);
+ ern++;
+ QSlog("bad i = %d", i);
+ }
+ }
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (err))
+ QSlog("dI x err = %.7f, ern = %d", EGLPNUM_TYPENAME_EGlpNumToLf (err), ern);
+ EGLPNUM_TYPENAME_ILLprice_compute_primal_inf (lp, p, NULL, 0, DUAL_PHASEI);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (x);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (diff);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (err);
+}
+
+void EGLPNUM_TYPENAME_fct_test_pII_x (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * p)
+{
+ int i;
+ int ern = 0;
+ EGLPNUM_TYPE *x;
+ EGLPNUM_TYPE err, diff;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (err);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (diff);
+ EGLPNUM_TYPENAME_EGlpNumZero (err);
+ x = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+
+ for (i = 0; i < lp->nrows; i++)
+ EGLPNUM_TYPENAME_EGlpNumCopy (x[i], lp->xbz[i]);
+ EGLPNUM_TYPENAME_ILLfct_compute_xbz (lp);
+ for (i = 0; i < lp->nrows; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (diff, x[i], lp->xbz[i]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (diff ))
+ EGLPNUM_TYPENAME_EGlpNumSign (diff);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_PFEAS_TOLER, diff))
+ {
+ EGLPNUM_TYPENAME_EGlpNumAddTo (err, diff);
+ ern++;
+ QSlog("bad i = %d", i);
+ }
+ }
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (err))
+ QSlog("dII x err = %.7f, ern = %d", EGLPNUM_TYPENAME_EGlpNumToLf (err), ern);
+ EGLPNUM_TYPENAME_ILLprice_compute_primal_inf (lp, p, NULL, 0, DUAL_PHASEII);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (x);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (diff);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (err);
+}
+
+void EGLPNUM_TYPENAME_fct_test_pI_pi_dz (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * p)
+{
+ int i;
+ int ern = 0;
+ EGLPNUM_TYPE *pidz;
+ EGLPNUM_TYPE err, diff;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (err);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (diff);
+ pidz = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->ncols);
+ EGLPNUM_TYPENAME_EGlpNumZero (err);
+
+ for (i = 0; i < lp->nrows; i++)
+ EGLPNUM_TYPENAME_EGlpNumCopy (pidz[i], lp->pIpiz[i]);
+ EGLPNUM_TYPENAME_ILLfct_compute_phaseI_piz (lp);
+ for (i = 0; i < lp->nrows; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (diff, pidz[i], lp->pIpiz[i]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (diff))
+ EGLPNUM_TYPENAME_EGlpNumSign (diff);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_DFEAS_TOLER, diff))
+ {
+ EGLPNUM_TYPENAME_EGlpNumAddTo (err, diff);
+ ern++;
+ }
+ }
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (err))
+ QSlog("pI pi err = %.7f, ern = %d", EGLPNUM_TYPENAME_EGlpNumToLf (err), ern);
+
+ EGLPNUM_TYPENAME_EGlpNumZero (err);
+ ern = 0;
+ for (i = 0; i < lp->nnbasic; i++)
+ EGLPNUM_TYPENAME_EGlpNumCopy (pidz[i], lp->pIdz[i]);
+ EGLPNUM_TYPENAME_ILLfct_compute_phaseI_dz (lp);
+ for (i = 0; i < lp->nnbasic; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (diff, pidz[i], lp->pIdz[i]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (diff))
+ EGLPNUM_TYPENAME_EGlpNumSign (diff);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_DFEAS_TOLER, diff))
+ {
+ EGLPNUM_TYPENAME_EGlpNumAddTo (err, diff);
+ ern++;
+ }
+ }
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (err))
+ QSlog("pI dz err = %.7f, ern = %d", EGLPNUM_TYPENAME_EGlpNumToLf (err), ern);
+ EGLPNUM_TYPENAME_ILLprice_compute_dual_inf (lp, p, NULL, 0, PRIMAL_PHASEI);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (err);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (diff);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (pidz);
+}
+
+void EGLPNUM_TYPENAME_fct_test_pII_pi_dz (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * p)
+{
+ int i;
+ int ern = 0;
+ EGLPNUM_TYPE *pidz;
+ EGLPNUM_TYPE err, diff;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (err);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (diff);
+ EGLPNUM_TYPENAME_EGlpNumZero (err);
+ pidz = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->ncols);
+
+ for (i = 0; i < lp->nrows; i++)
+ EGLPNUM_TYPENAME_EGlpNumCopy (pidz[i], lp->piz[i]);
+ EGLPNUM_TYPENAME_ILLfct_compute_piz (lp);
+ for (i = 0; i < lp->nrows; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (diff, pidz[i], lp->piz[i]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (diff))
+ EGLPNUM_TYPENAME_EGlpNumSign (diff);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_DFEAS_TOLER, diff))
+ {
+ EGLPNUM_TYPENAME_EGlpNumAddTo (err, diff);
+ ern++;
+ }
+ }
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (err))
+ QSlog("pII pi err = %.7f, ern = %d", EGLPNUM_TYPENAME_EGlpNumToLf (err), ern);
+
+ EGLPNUM_TYPENAME_EGlpNumZero (err);
+ ern = 0;
+ for (i = 0; i < lp->nnbasic; i++)
+ EGLPNUM_TYPENAME_EGlpNumCopy (pidz[i], lp->dz[i]);
+ EGLPNUM_TYPENAME_ILLfct_compute_dz (lp);
+ for (i = 0; i < lp->nnbasic; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (diff, pidz[i], lp->dz[i]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (diff))
+ EGLPNUM_TYPENAME_EGlpNumSign (diff);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_DFEAS_TOLER, diff))
+ {
+ EGLPNUM_TYPENAME_EGlpNumAddTo (err, diff);
+ ern++;
+ }
+ }
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (err))
+ QSlog("pII dz err = %.7f, ern = %d", EGLPNUM_TYPENAME_EGlpNumToLf (err), ern);
+ /*
+ * EGLPNUM_TYPENAME_ILLprice_compute_dual_inf (lp, p, NULL, 0, PRIMAL_PHASEII);
+ */
+ EGLPNUM_TYPENAME_EGlpNumClearVar (err);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (diff);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (pidz);
+}
+
+#endif
diff --git a/qsopt_ex/fct.h b/qsopt_ex/fct.h
new file mode 100644
index 0000000..acee452
--- /dev/null
+++ b/qsopt_ex/fct.h
@@ -0,0 +1,250 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCSINFO $Id: fct_EGLPNUM_TYPENAME.h,v 1.3 2003/11/05 16:57:39 meven Exp $ */
+#ifndef EGLPNUM_TYPENAME___FUNCTIONS_H
+#define EGLPNUM_TYPENAME___FUNCTIONS_H
+
+#include "basicdefs.h"
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+
+
+int EGLPNUM_TYPENAME_ILLfct_compute_zA (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * z,
+ EGLPNUM_TYPENAME_svector * zA),
+ EGLPNUM_TYPENAME_ILLfct_compute_wz (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPE * wz),
+ EGLPNUM_TYPENAME_ILLfct_adjust_viol_bounds (
+ EGLPNUM_TYPENAME_lpinfo * lp),
+ EGLPNUM_TYPENAME_ILLfct_perturb_bounds (
+ EGLPNUM_TYPENAME_lpinfo * lp),
+ EGLPNUM_TYPENAME_ILLfct_perturb_phaseI_bounds (
+ EGLPNUM_TYPENAME_lpinfo * lp),
+ EGLPNUM_TYPENAME_ILLfct_bound_shift (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int col,
+ int bndtype,
+ EGLPNUM_TYPE newbnd),
+ EGLPNUM_TYPENAME_ILLfct_adjust_viol_coefs (
+ EGLPNUM_TYPENAME_lpinfo * lp),
+ EGLPNUM_TYPENAME_ILLfct_perturb_coefs (
+ EGLPNUM_TYPENAME_lpinfo * lp),
+ EGLPNUM_TYPENAME_ILLfct_coef_shift (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int col,
+ EGLPNUM_TYPE newcoef),
+ EGLPNUM_TYPENAME_ILLfct_test_pivot (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int indx,
+ int indxtype,
+ EGLPNUM_TYPE piv_val);
+
+void EGLPNUM_TYPENAME_ILLfct_load_workvector (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * s),
+ EGLPNUM_TYPENAME_ILLfct_zero_workvector (
+ EGLPNUM_TYPENAME_lpinfo * lp),
+ EGLPNUM_TYPENAME_ILLfct_set_variable_type (
+ EGLPNUM_TYPENAME_lpinfo * lp),
+ EGLPNUM_TYPENAME_ILLfct_compute_pobj (
+ EGLPNUM_TYPENAME_lpinfo * lp),
+ EGLPNUM_TYPENAME_ILLfct_compute_dobj (
+ EGLPNUM_TYPENAME_lpinfo * lp),
+ EGLPNUM_TYPENAME_ILLfct_compute_xbz (
+ EGLPNUM_TYPENAME_lpinfo * lp),
+ EGLPNUM_TYPENAME_ILLfct_compute_piz (
+ EGLPNUM_TYPENAME_lpinfo * lp),
+ EGLPNUM_TYPENAME_ILLfct_compute_phaseI_xbz (
+ EGLPNUM_TYPENAME_lpinfo * lp),
+ EGLPNUM_TYPENAME_ILLfct_compute_phaseI_piz (
+ EGLPNUM_TYPENAME_lpinfo * lp),
+ EGLPNUM_TYPENAME_ILLfct_compute_dz (
+ EGLPNUM_TYPENAME_lpinfo * lp),
+ EGLPNUM_TYPENAME_ILLfct_compute_phaseI_dz (
+ EGLPNUM_TYPENAME_lpinfo * lp),
+ EGLPNUM_TYPENAME_ILLfct_compute_yz (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * yz,
+ EGLPNUM_TYPENAME_svector * updz,
+ int ecol),
+ EGLPNUM_TYPENAME_ILLfct_compute_zz (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * zz,
+ int lindex),
+ EGLPNUM_TYPENAME_ILLfct_compute_binvrow (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * zz,
+ int row,
+ EGLPNUM_TYPE ztoler),
+ EGLPNUM_TYPENAME_ILLfct_compute_vA (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * v,
+ EGLPNUM_TYPE * vA),
+ EGLPNUM_TYPENAME_ILLfct_compute_psteep_upv (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * swz),
+ EGLPNUM_TYPENAME_ILLfct_compute_dsteep_upv (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * swz),
+ EGLPNUM_TYPENAME_ILLfct_update_basis_info (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int eindex,
+ int lindex,
+ int lvstat),
+ EGLPNUM_TYPENAME_ILLfct_update_xz (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPE tz,
+ int eindex,
+ int lindex),
+ EGLPNUM_TYPENAME_ILLfct_update_piz (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPE alpha),
+ EGLPNUM_TYPENAME_ILLfct_update_pIpiz (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * z,
+ const EGLPNUM_TYPE alpha),
+ EGLPNUM_TYPENAME_ILLfct_update_dz (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int eindex,
+ EGLPNUM_TYPE alpha),
+ EGLPNUM_TYPENAME_ILLfct_update_pIdz (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * zA,
+ int eindex,
+ const EGLPNUM_TYPE alpha),
+ EGLPNUM_TYPENAME_ILLfct_unroll_bound_change (
+ EGLPNUM_TYPENAME_lpinfo * lp),
+ EGLPNUM_TYPENAME_ILLfct_unroll_coef_change (
+ EGLPNUM_TYPENAME_lpinfo * lp),
+ EGLPNUM_TYPENAME_ILLfct_check_pfeasible (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_feas_info * fs,
+ const EGLPNUM_TYPE ftol),
+ EGLPNUM_TYPENAME_ILLfct_check_pIpfeasible (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_feas_info * fs,
+ EGLPNUM_TYPE ftol),
+ EGLPNUM_TYPENAME_ILLfct_check_dfeasible (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_feas_info * fs,
+ const EGLPNUM_TYPE ftol),
+ EGLPNUM_TYPENAME_ILLfct_dual_adjust (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ const EGLPNUM_TYPE ftol),
+ EGLPNUM_TYPENAME_ILLfct_dphaseI_simple_update (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPE ftol),
+ EGLPNUM_TYPENAME_ILLfct_set_status_values (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int pstatus,
+ int dstatus,
+ int ptype,
+ int dtype),
+ EGLPNUM_TYPENAME_ILLfct_init_counts (
+ EGLPNUM_TYPENAME_lpinfo * lp),
+ EGLPNUM_TYPENAME_ILLfct_update_counts (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int f,
+ int upi,
+ const EGLPNUM_TYPE upd),
+ EGLPNUM_TYPENAME_ILLfct_print_counts (
+ EGLPNUM_TYPENAME_lpinfo * lp),
+ EGLPNUM_TYPENAME_ILLfct_check_pIdfeasible (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_feas_info * fs,
+ EGLPNUM_TYPE ftol),
+ EGLPNUM_TYPENAME_ILLfct_update_pfeas (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int lindex,
+ EGLPNUM_TYPENAME_svector * srhs),
+ EGLPNUM_TYPENAME_ILLfct_compute_ppIzz (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * srhs,
+ EGLPNUM_TYPENAME_svector * ssoln),
+ EGLPNUM_TYPENAME_ILLfct_update_ppI_prices (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * pinf,
+ EGLPNUM_TYPENAME_svector * srhs,
+ EGLPNUM_TYPENAME_svector * ssoln,
+ int eindex,
+ int lindex,
+ const EGLPNUM_TYPE alpha),
+ EGLPNUM_TYPENAME_ILLfct_update_dfeas (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int eindex,
+ EGLPNUM_TYPENAME_svector * srhs),
+ EGLPNUM_TYPENAME_ILLfct_compute_dpIy (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * srhs,
+ EGLPNUM_TYPENAME_svector * ssoln),
+ EGLPNUM_TYPENAME_ILLfct_update_dpI_prices (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * pinf,
+ EGLPNUM_TYPENAME_svector * srhs,
+ EGLPNUM_TYPENAME_svector * ssoln,
+ int lindex,
+ EGLPNUM_TYPE alpha),
+ EGLPNUM_TYPENAME_ILLfct_update_dIIfeas (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int eindex,
+ EGLPNUM_TYPENAME_svector * srhs),
+ EGLPNUM_TYPENAME_ILLfct_compute_dpIIy (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_svector * srhs,
+ EGLPNUM_TYPENAME_svector * ssoln),
+ EGLPNUM_TYPENAME_ILLfct_update_dpII_prices (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * pinf,
+ EGLPNUM_TYPENAME_svector * srhs,
+ EGLPNUM_TYPENAME_svector * ssoln,
+ /*int eindex,*/
+ int lindex,
+ EGLPNUM_TYPE eval,
+ EGLPNUM_TYPE alpha);
+
+void EGLPNUM_TYPENAME_fct_test_workvector (
+ EGLPNUM_TYPENAME_lpinfo * lp),
+ EGLPNUM_TYPENAME_fct_test_pfeasible (
+ EGLPNUM_TYPENAME_lpinfo * lp),
+ EGLPNUM_TYPENAME_fct_test_dfeasible (
+ EGLPNUM_TYPENAME_lpinfo * lp),
+ EGLPNUM_TYPENAME_fct_test_pI_x (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * p),
+ EGLPNUM_TYPENAME_fct_test_pII_x (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * p),
+ EGLPNUM_TYPENAME_fct_test_pI_pi_dz (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * p),
+ EGLPNUM_TYPENAME_fct_test_pII_pi_dz (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * p);
+
+EGLPNUM_TYPENAME_bndinfo *EGLPNUM_TYPENAME_ILLfct_new_bndinfo (
+ void);
+void EGLPNUM_TYPENAME_ILLfct_free_bndinfo (
+ EGLPNUM_TYPENAME_bndinfo * binfo);
+
+#endif /* EGLPNUM_TYPENAME___FUNCTIONS_H */
diff --git a/qsopt_ex/format.c b/qsopt_ex/format.c
new file mode 100644
index 0000000..76f7615
--- /dev/null
+++ b/qsopt_ex/format.c
@@ -0,0 +1,231 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: format_error.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "qs_config.h"
+
+#include "eg_io.h"
+#include "except.h"
+
+#include "format_EGLPNUM_TYPENAME.h"
+#include "qsopt_EGLPNUM_TYPENAME.h"
+
+
+int EGLPNUM_TYPENAME_ILLformat_error_create (
+ EGLPNUM_TYPENAME_qsformat_error * error,
+ int mode,
+ const char *desc,
+ int lineNum,
+ const char *theLine,
+ int atPos)
+{
+ int len;
+ int rval = 0;
+
+ error->theLine = NULL;
+ error->desc = NULL;
+ error->next = NULL;
+
+ ILL_FAILtrue (desc == NULL, "non empty error desc please");
+ ILL_FAILtrue (mode >= QS_INPUT_NERROR
+ || mode < 0, "0<= mode <=QS_INPUT_NERROR");
+ error->type = mode;
+ len = strlen (desc);
+ ILL_SAFE_MALLOC (error->desc, len + 1, char);
+
+ strcpy (error->desc, desc);
+ error->lineNumber = lineNum;
+ if (theLine != NULL)
+ {
+ len = strlen (theLine);
+ ILL_SAFE_MALLOC (error->theLine, len + 2, char);
+
+ strcpy (error->theLine, theLine);
+ if (error->theLine[len - 1] != '\n')
+ {
+ error->theLine[len] = '\n';
+ error->theLine[len + 1] = '\0';
+ }
+ }
+ error->at = atPos;
+CLEANUP:
+ if (rval)
+ {
+ EGLPNUM_TYPENAME_ILLformat_error_delete (error);
+ }
+ return rval;
+}
+
+void EGLPNUM_TYPENAME_ILLformat_error_delete (
+ EGLPNUM_TYPENAME_qsformat_error * error)
+{
+ ILL_IFFREE (error->desc, char);
+ ILL_IFFREE (error->theLine, char);
+}
+
+void EGLPNUM_TYPENAME_ILLformat_error_print (
+ EGioFile_t * out,
+ EGLPNUM_TYPENAME_qsformat_error * error)
+{
+ int at = error->at;
+ int tp = error->type;
+ const char *type = "Error";
+ const char *line = NULL;
+ int i;
+
+ type = EGLPNUM_TYPENAME_QSformat_error_type_string (tp);
+
+ EGioPrintf (out, "%s line %d pos %d\n",
+ type, EGLPNUM_TYPENAME_QSerror_get_line_number (error), at);
+ line = EGLPNUM_TYPENAME_QSerror_get_line (error);
+ if (line != NULL)
+ {
+ EGioPrintf (out, "LINE %s", line);
+ if (at >= 0)
+ {
+ EGioPrintf (out, ".....");
+ for (i = 0; i <= (at - 1); i++)
+ {
+ if (line[i] == '\t')
+ {
+ EGioPrintf(out, "\t");
+ }
+ else
+ {
+ EGioPrintf(out, ".");
+ }
+ }
+ EGioPrintf (out, "^\n");
+ }
+ }
+ else
+ {
+ EGioPrintf (out, "NO LINE\n");
+ }
+ EGioPrintf (out, "MSG: %s\n", EGLPNUM_TYPENAME_QSerror_get_desc (error));
+}
+
+
+EGLPNUM_TYPENAME_qserror_collector *EGLPNUM_TYPENAME_ILLerror_collector_new (
+ EGLPNUM_TYPENAME_qsadd_error_fct fct,
+ void *dest)
+{
+ int rval = 0;
+ EGLPNUM_TYPENAME_qserror_collector *c = NULL;
+
+ ILL_SAFE_MALLOC (c, 1, EGLPNUM_TYPENAME_qserror_collector);
+ c->add_error = fct;
+ c->dest = dest;
+
+CLEANUP:
+ if (rval)
+ {
+ ILL_IFFREE (c, EGLPNUM_TYPENAME_qserror_collector);
+ }
+ return c;
+}
+
+EGLPNUM_TYPENAME_qserror_collector *EGLPNUM_TYPENAME_ILLerror_memory_collector_new (
+ EGLPNUM_TYPENAME_qserror_memory * dest)
+{
+ return EGLPNUM_TYPENAME_ILLerror_collector_new (EGLPNUM_TYPENAME_ILLadd_error_to_memory, dest);
+}
+
+void EGLPNUM_TYPENAME_ILLerror_collector_free (
+ EGLPNUM_TYPENAME_qserror_collector * c)
+{
+ ILL_IFFREE (c, EGLPNUM_TYPENAME_qserror_collector);
+}
+
+EGLPNUM_TYPENAME_qserror_memory *EGLPNUM_TYPENAME_ILLerror_memory_create (
+ int takeErrorLines)
+{
+ int rval = 0, i;
+ EGLPNUM_TYPENAME_qserror_memory *mem = NULL;
+
+ ILL_SAFE_MALLOC (mem, 1, EGLPNUM_TYPENAME_qserror_memory);
+ for (i = 0; i < QS_INPUT_NERROR; i++)
+ {
+ mem->has_error[i] = 0;
+ }
+ mem->error_list = NULL;
+ mem->nerror = 0;
+ mem->hasErrorLines = takeErrorLines;
+CLEANUP:
+ return mem;
+}
+
+void EGLPNUM_TYPENAME_ILLerror_memory_free (
+ EGLPNUM_TYPENAME_qserror_memory * mem)
+{
+ EGLPNUM_TYPENAME_qsformat_error *ths, *nxt;
+
+ if (mem != NULL)
+ {
+ ths = mem->error_list;
+ while (ths != NULL)
+ {
+ nxt = ths->next;
+ ILL_IFFREE (ths, EGLPNUM_TYPENAME_qsformat_error);
+ ths = nxt;
+ }
+ ILL_IFFREE (mem, EGLPNUM_TYPENAME_qserror_memory);
+ }
+}
+
+int EGLPNUM_TYPENAME_ILLadd_error_to_memory (
+ void *dest,
+ const EGLPNUM_TYPENAME_qsformat_error * error)
+{
+ int rval = 0;
+ EGLPNUM_TYPENAME_qserror_memory *mem = (EGLPNUM_TYPENAME_qserror_memory *) dest;
+ EGLPNUM_TYPENAME_qsformat_error *e = 0;
+
+ ILL_CHECKnull (mem, "must give non NULL EGLPNUM_TYPENAME_qserror_memory");
+
+ ILL_SAFE_MALLOC (e, 1, EGLPNUM_TYPENAME_qsformat_error);
+ rval = EGLPNUM_TYPENAME_ILLformat_error_create (e, error->type, error->desc,
+ error->lineNumber,
+ (mem->hasErrorLines) ? error->theLine : NULL,
+ error->at);
+ ILL_CLEANUP_IF (rval);
+ e->next = mem->error_list;
+ mem->error_list = e;
+ mem->nerror++;
+ mem->has_error[error->type]++;
+
+CLEANUP:
+ if (rval)
+ {
+ EGLPNUM_TYPENAME_ILLformat_error_delete (e);
+ ILL_IFFREE (e, EGLPNUM_TYPENAME_qsformat_error);
+ }
+ return rval;
+}
diff --git a/qsopt_ex/format.h b/qsopt_ex/format.h
new file mode 100644
index 0000000..44ef43d
--- /dev/null
+++ b/qsopt_ex/format.h
@@ -0,0 +1,137 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCSINFO $Id: format_EGLPNUM_TYPENAME.h,v 1.3 2003/11/05 16:59:48 meven Exp $ */
+#ifndef EGLPNUM_TYPENAME_QS_FORMAT_ERROR_H
+#define EGLPNUM_TYPENAME_QS_FORMAT_ERROR_H
+
+#include <stdio.h>
+
+#include "qsopt_EGLPNUM_TYPENAME.h"
+#include "eg_io.h"
+
+/****************************************************************************/
+/*
+ The LP/MPS readers, writers,
+ EGLPNUM_TYPENAME_ILLrawlpdata_to_lpdata, and
+ use EGLPNUM_TYPENAME_ILLformat_error to report problems with their input iff
+ the line reader used in reading the problem or
+ the EGLPNUM_TYPENAME_qserror_collector pointer passed to EGLPNUM_TYPENAME_ILLwrite_lp_file
+ is not NULL.
+
+ The QSgui code uses this feature to collect EGLPNUM_TYPENAME_qsformat_error instances
+ which it uses after reading is done to insert error messages into the
+ input window.
+*/
+/****************************************************************************/
+
+/*
+for error type USE:
+ QS_DATA_ERROR
+ QS_DATA_WARN
+ QS_MPS_FORMAT_ERROR
+ QS_MPS_FORMAT_WARN
+ QS_LP_FORMAT_ERROR
+ QS_LP_FORMAT_WARN
+ QS_LP_OBJ_WARN
+ QS_GENERIC_ERROR
+*/
+
+typedef struct EGLPNUM_TYPENAME_qsformat_error
+{
+ char *desc;
+ char *theLine;
+ struct EGLPNUM_TYPENAME_qsformat_error *next;
+ int type;
+ int lineNumber; /* 1 based line counting */
+ int at;
+}
+EGLPNUM_TYPENAME_qsformat_error;
+
+extern int EGLPNUM_TYPENAME_ILLformat_error_create (
+ EGLPNUM_TYPENAME_qsformat_error * error,
+ int mode,
+ const char *desc,
+ int lineNum,
+ const char *theLine,
+ int atPos);
+extern void EGLPNUM_TYPENAME_ILLformat_error_delete (
+ EGLPNUM_TYPENAME_qsformat_error * error);
+
+extern void EGLPNUM_TYPENAME_ILLformat_error_print (
+ EGioFile_t * out,
+ EGLPNUM_TYPENAME_qsformat_error * e);
+
+
+
+/*****************************************************************************
+ * collecting error messages
+ * either with defining own qsad_error_fct and corresponding data structure
+ * or by using predefined EGLPNUM_TYPENAME_ILLadd_error_to_memory fct with EGLPNUM_TYPENAME_qserror_memory
+ */
+
+typedef int (
+ *EGLPNUM_TYPENAME_qsadd_error_fct) (
+ void *dest,
+ const EGLPNUM_TYPENAME_qsformat_error * error);
+
+typedef struct EGLPNUM_TYPENAME_qserror_collector
+{
+ EGLPNUM_TYPENAME_qsadd_error_fct add_error;
+ void *dest;
+}
+EGLPNUM_TYPENAME_qserror_collector;
+
+typedef struct EGLPNUM_TYPENAME_qserror_memory
+{
+ unsigned int nerror;
+ EGLPNUM_TYPENAME_qsformat_error *error_list;
+ char has_error[QS_INPUT_NERROR];
+ char hasErrorLines;
+}
+EGLPNUM_TYPENAME_qserror_memory;
+
+
+extern EGLPNUM_TYPENAME_qserror_collector *EGLPNUM_TYPENAME_ILLerror_collector_new (
+ EGLPNUM_TYPENAME_qsadd_error_fct fct,
+ void *dest);
+
+EGLPNUM_TYPENAME_qserror_collector *EGLPNUM_TYPENAME_ILLerror_memory_collector_new (
+ EGLPNUM_TYPENAME_qserror_memory * dest);
+
+extern void EGLPNUM_TYPENAME_ILLerror_collector_free (
+ EGLPNUM_TYPENAME_qserror_collector * c);
+
+#define EGLPNUM_TYPENAME_ILLformat_error(collector, error) \
+ ((collector)->add_error((collector)->dest, error))
+
+
+extern int EGLPNUM_TYPENAME_ILLadd_error_to_memory (
+ void *dest,
+ const EGLPNUM_TYPENAME_qsformat_error * error);
+
+extern EGLPNUM_TYPENAME_qserror_memory *EGLPNUM_TYPENAME_ILLerror_memory_create (
+ int takeErrorLines);
+extern void EGLPNUM_TYPENAME_ILLerror_memory_free (
+ EGLPNUM_TYPENAME_qserror_memory * mem);
+
+#endif
diff --git a/qsopt_ex/lib.c b/qsopt_ex/lib.c
new file mode 100644
index 0000000..fdd7fa7
--- /dev/null
+++ b/qsopt_ex/lib.c
@@ -0,0 +1,4348 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: lib.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+//static int TRACE = 0;
+
+/****************************************************************************/
+/* */
+/* Interface Routines to Core LP Solver */
+/* */
+/* EXPORTED FUNCTIONS */
+/* */
+/* int EGLPNUM_TYPENAME_ILLlib_optimize (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_basis *B, EGLPNUM_TYPENAME_price_info *pinf, */
+/* int algo, int *status, int simplex_display) */
+/* int EGLPNUM_TYPENAME_ILLlib_cache_solution (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_cache *C) */
+/* int EGLPNUM_TYPENAME_ILLlib_solution (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_cache *C, double *val, */
+/* double *x, double *pi, double *slack, double *rc) */
+/* int EGLPNUM_TYPENAME_ILLlib_get_x (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_cache *C, double *x) */
+/* int EGLPNUM_TYPENAME_ILLlib_get_slack (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_cache *C, double *slack) */
+/* int EGLPNUM_TYPENAME_ILLlib_objval (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_cache *C, double *val) */
+/* int EGLPNUM_TYPENAME_ILLlib_newrow (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_basis *B, double rhs, */
+/* char sense, double range, const char *name) */
+/* -range can specify a rangeval for the row (if sense is not 'R', */
+/* then range is ignored); it should be 0 if no range is needed; */
+/* if sense is 'R' but no rangeval array exists for the LP, the */
+/* array will be allocated and initialized. */
+/* int EGLPNUM_TYPENAME_ILLlib_newrows (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_basis *B, int num, double *rhs, */
+/* char *sense, double *range, const char **names) */
+/* -range is an array specifying the rangevals for the rows; range */
+/* should be NULL if no rangevals are needed. */
+/* int EGLPNUM_TYPENAME_ILLlib_addrow (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_basis *B, int cnt, int *ind, */
+/* double *val, double rhs, char sense, double range, */
+/* const char *name) */
+/* int EGLPNUM_TYPENAME_ILLlib_addrows (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_basis *B, int num, */
+/* int *rmatcnt, int *rmatbeg, int *rmatind, double *rmatval, */
+/* double *rhs, char *sense, double *range, const char **names, */
+/* int *factorok) */
+/* int EGLPNUM_TYPENAME_ILLlib_delrows (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_basis *B, */
+/* int num, int *dellist, int *basis_ok) */
+/* int EGLPNUM_TYPENAME_ILLlib_newcol (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_basis *B, */
+/* double obj, double lower, double upper, const char *name, */
+/* int factorok) */
+/* int EGLPNUM_TYPENAME_ILLlib_newcols (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_basis *B, */
+/* int num, double *obj, double *lower, double *upper, */
+/* const char **names, int factorok) */
+/* int EGLPNUM_TYPENAME_ILLlib_addcol (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_basis *B, */
+/* int cnt, int *ind, double *val, double obj, double lower, */
+/* double upper, const char *name, int factorok) */
+/* int EGLPNUM_TYPENAME_ILLlib_addcols (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_basis *B, */
+/* int num, int *cmatcnt, int *cmatbeg, int *cmatind, */
+/* double *cmatval, double *obj, double *lower, double *upper, */
+/* const char **names, int factorok) */
+/* int EGLPNUM_TYPENAME_ILLlib_delcols (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_basis *B, int num, int *dellist */
+/* int *basis_ok) */
+/* int EGLPNUM_TYPENAME_ILLlib_chgcoef (EGLPNUM_TYPENAME_lpinfo *lp, int rowindex, int colindex, */
+/* double coef) */
+/* int EGLPNUM_TYPENAME_ILLlib_chgsense (EGLPNUM_TYPENAME_lpinfo *lp, int num, int *rowlist, char *sense) */
+/* int EGLPNUM_TYPENAME_ILLlib_getrows (EGLPNUM_TYPENAME_lpinfo *lp, int num, int *rowlist, int **rowcnt, */
+/* int **rowbeg, int **rowind, double **rowval, double **rhs, */
+/* char **sense, char ***names) */
+/* int EGLPNUM_TYPENAME_ILLlib_getcols (EGLPNUM_TYPENAME_lpinfo *lp, int num, int *collist, int **colcnt, */
+/* int **colbeg, int **colind, double **colval, double **obj, */
+/* double **lower, double **upper, char ***names) */
+/* int EGLPNUM_TYPENAME_ILLlib_getobj (EGLPNUM_TYPENAME_lpinfo *lp, double *obj) */
+/* int EGLPNUM_TYPENAME_ILLlib_chgobj (EGLPNUM_TYPENAME_lpinfo *lp, int indx, double coef) */
+/* int EGLPNUM_TYPENAME_ILLlib_getrhs (EGLPNUM_TYPENAME_lpinfo *lp, double *rhs) */
+/* int EGLPNUM_TYPENAME_ILLlib_chgrhs (EGLPNUM_TYPENAME_lpinfo *lp, int indx, double coef) */
+/* int EGLPNUM_TYPENAME_ILLlib_getintflags (EGLPNUM_TYPENAME_lpinfo *lp, int *intflags) */
+/* int EGLPNUM_TYPENAME_ILLlib_rownames (EGLPNUM_TYPENAME_lpinfo *lp, char **rownames) */
+/* int EGLPNUM_TYPENAME_ILLlib_colnames (EGLPNUM_TYPENAME_lpinfo *lp, char **colnames) */
+/* int EGLPNUM_TYPENAME_ILLlib_colindex (EGLPNUM_TYPENAME_lpinfo *lp, char *name, int *colindex) */
+/* int EGLPNUM_TYPENAME_ILLlib_rowindex (EGLPNUM_TYPENAME_lpinfo *lp, char *name, int *rowindex) */
+/* int EGLPNUM_TYPENAME_ILLlib_chgbnd (EGLPNUM_TYPENAME_lpinfo *lp, int indx, char lu, double bnd) */
+/* int EGLPNUM_TYPENAME_ILLlib_chgbnds (EGLPNUM_TYPENAME_lpinfo *lp, int cnt, int *indx, char *lu, */
+/* double *bnd) */
+/* int EGLPNUM_TYPENAME_ILLlib_getbnd (EGLPNUM_TYPENAME_lpinfo *lp, int indx, char lu, double *bnd) */
+/* int EGLPNUM_TYPENAME_ILLlib_getbnds (EGLPNUM_TYPENAME_lpinfo *lp, double *lower, double *upper) */
+/* int EGLPNUM_TYPENAME_ILLlib_strongbranch (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_price_info *pinf, */
+/* int *candidatelist, int ncand, double *xlist, double *downpen, */
+/* double *uppen, int iterations, double objbound) */
+/* int EGLPNUM_TYPENAME_ILLlib_getbasis (EGLPNUM_TYPENAME_lpinfo *lp, char *cstat, char *rstat) */
+/* int EGLPNUM_TYPENAME_ILLlib_loadbasis (EGLPNUM_TYPENAME_ILLlp_basis *B, int nstruct, int nrows, */
+/* char *cstat, char *rstat) */
+/* int EGLPNUM_TYPENAME_ILLlib_readbasis (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_basis *B, char *fname) */
+/* int EGLPNUM_TYPENAME_ILLlib_writebasis (EGLPNUM_TYPENAME_lpinfo *lp, const char *fname) */
+/* int EGLPNUM_TYPENAME_ILLlib_getrownorms (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_price_info *pinf, */
+/* double *rownorms) */
+/* int EGLPNUM_TYPENAME_ILLlib_loadrownorms (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_price_info *pinf, */
+/* double *rownorms) */
+/* int EGLPNUM_TYPENAME_ILLlib_recompute_rownorms (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_price_info *pinf) */
+/* int EGLPNUM_TYPENAME_ILLlib_print_x (EGioFile_t *fd, EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_cache *C, double *x, */
+/* int nonZerosOnly) */
+/* int EGLPNUM_TYPENAME_ILLlib_print_x (EGLPNUM_TYPENAME_lpinfo *lp, EGLPNUM_TYPENAME_ILLlp_cache *C) */
+/* int EGLPNUM_TYPENAME_ILLlib_iter (EGLPNUM_TYPENAME_lpinfo *lp) */
+/* */
+/* NOTES */
+/* */
+/* */
+/****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "eg_lpnum.h"
+#include "eg_io.h"
+#include "except.h"
+#include "util.h"
+
+#include "lpdata_EGLPNUM_TYPENAME.h"
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+#include "simplex_EGLPNUM_TYPENAME.h"
+#include "price_EGLPNUM_TYPENAME.h"
+#include "basis_EGLPNUM_TYPENAME.h"
+#include "lib_EGLPNUM_TYPENAME.h"
+#include "qstruct_EGLPNUM_TYPENAME.h"
+#include "qsopt_EGLPNUM_TYPENAME.h"
+#include "lp_EGLPNUM_TYPENAME.h"
+#include "mps_EGLPNUM_TYPENAME.h"
+
+
+static void check_pinf (
+ EGLPNUM_TYPENAME_price_info * pinf,
+ int *it_exists);
+
+static int matrix_addrow (
+ EGLPNUM_TYPENAME_ILLmatrix * A,
+ int rowcnt,
+ int *rowind,
+ const EGLPNUM_TYPE * rowval),
+ matrix_addrow_end (
+ EGLPNUM_TYPENAME_ILLmatrix * A,
+ int row,
+ int rowcnt,
+ int *rowind,
+ const EGLPNUM_TYPE * rowval),
+ matrix_addcoef (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_ILLmatrix * A,
+ int row,
+ int col,
+ EGLPNUM_TYPE val),
+ matrix_addcol (
+ EGLPNUM_TYPENAME_ILLmatrix * A,
+ int colcnt,
+ int *colind,
+ EGLPNUM_TYPE * colval),
+ delcols_work (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ char *colmark),
+ reset_colindex (
+ EGLPNUM_TYPENAME_lpinfo * lp),
+ reset_rowindex (
+ EGLPNUM_TYPENAME_lpinfo * lp);
+
+int EGLPNUM_TYPENAME_ILLlib_optimize (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_ILLlp_basis * B,
+ EGLPNUM_TYPENAME_price_info * pinf,
+ int algo,
+ int *status,
+ int simplex_display,
+ itcnt_t*itcnt)
+{
+ int rval = 0;
+ int sol_status;
+
+ if (status)
+ *status = QS_LP_UNSOLVED;
+
+ /* EGLPNUM_TYPENAME_ILLprice_free_pricing_info (pinf); *//* Should be removed later */
+
+ rval = EGLPNUM_TYPENAME_ILLsimplex (lp, algo, B, pinf, &sol_status, simplex_display, itcnt);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (status)
+ *status = sol_status;
+
+CLEANUP:
+
+ if (rval == E_SIMPLEX_ERROR)
+ {
+ EGioFile_t *eout = 0;
+ int tval;
+
+ QSlog("write bad lp to error.lp");
+#ifdef HAVE_LIBZ
+ eout = EGioOpen ("error.lp.gz", "w");
+#else
+#ifdef HAVE_LIBBZ2
+ eout = EGioOpen ("error.lp.bz2", "w");
+#else
+ eout = EGioOpen ("error.lp", "w");
+#endif
+#endif
+ if (!eout)
+ {
+ QSlog("could not open file to write bad lp");
+ }
+ else
+ {
+ tval = EGLPNUM_TYPENAME_ILLwrite_lp (lp->O, NULL);
+ if (tval)
+ {
+ QSlog("error while writing bad lp");
+ }
+ EGioClose (eout);
+ }
+
+ QSlog("write bad basis to error.bas");
+ tval = EGLPNUM_TYPENAME_ILLlib_writebasis (lp, 0, "error.bas");
+ if (tval)
+ {
+ QSlog("error while writing bad basis");
+ }
+ }
+ if (rval == QS_LP_CHANGE_PREC)
+ {
+ MESSAGE (__QS_SB_VERB, "Changing precision");
+ return rval;
+ }
+ MESSAGE (rval ? 0 : 1000, "Error code %d", rval);
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_cache_solution (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_ILLlp_cache * C)
+{
+ int rval = 0;
+
+ if (C)
+ {
+ if (C->nstruct != lp->O->nstruct || C->nrows != lp->O->nrows)
+ {
+ QSlog("lp_cache does not match size of lp");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+ rval = EGLPNUM_TYPENAME_ILLlib_solution (lp, 0, &(C->val), C->x, C->pi, C->slack, C->rc);
+ CHECKRVALG (rval, CLEANUP);
+ }
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_solution (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_ILLlp_cache * C,
+ EGLPNUM_TYPE * val,
+ EGLPNUM_TYPE * x,
+ EGLPNUM_TYPE * pi,
+ EGLPNUM_TYPE * slack,
+ EGLPNUM_TYPE * rc)
+{
+ int i, rval = 0;
+ EGLPNUM_TYPE *tempx = 0;
+ EGLPNUM_TYPE *temprc = 0;
+ int ncols = lp->O->ncols;
+ int nrows = lp->O->nrows;
+ int nstruct = lp->O->nstruct;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp = lp->O;
+
+ if (C)
+ {
+ if (C->nrows != nrows || C->nstruct != nstruct)
+ {
+ QSlog("cache mismatch in EGLPNUM_TYPENAME_ILLlib_solution");
+ rval = 0;
+ ILL_CLEANUP;
+ }
+ if (val)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (*val, C->val);
+ }
+ if (x)
+ {
+ for (i = 0; i < nstruct; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (x[i], C->x[i]);
+ }
+ }
+ if (pi)
+ {
+ for (i = 0; i < nrows; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (pi[i], C->pi[i]);
+ }
+ }
+ if (slack)
+ {
+ for (i = 0; i < nrows; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (slack[i], C->slack[i]);
+ }
+ }
+ if (rc)
+ {
+ for (i = 0; i < nstruct; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (rc[i], C->rc[i]);
+ }
+ }
+ }
+ else
+ {
+ if (x || slack)
+ tempx = EGLPNUM_TYPENAME_EGlpNumAllocArray (ncols);
+
+ if (rc)
+ temprc = EGLPNUM_TYPENAME_EGlpNumAllocArray (ncols);
+
+ rval = EGLPNUM_TYPENAME_ILLsimplex_solution (lp, tempx, pi, temprc, val);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (x)
+ {
+ for (i = 0; i < nstruct; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (x[i], tempx[qslp->structmap[i]]);
+ }
+ }
+ if (slack)
+ {
+ for (i = 0; i < nrows; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (slack[i], tempx[qslp->rowmap[i]]);
+ }
+ }
+
+ if (rc)
+ {
+ for (i = 0; i < nstruct; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (rc[i], temprc[qslp->structmap[i]]);
+ }
+ }
+
+
+ if (lp->O->objsense == EGLPNUM_TYPENAME_ILL_MAX)
+ { /* Reverse signs for max prob */
+ if (val)
+ {
+ EGLPNUM_TYPENAME_EGlpNumSign (*val);
+ }
+ if (pi)
+ {
+ for (i = 0; i < nrows; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumSign (pi[i]);
+ }
+ }
+ if (rc)
+ {
+ for (i = 0; i < nstruct; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumSign (rc[i]);
+ }
+ }
+ }
+ }
+
+CLEANUP:
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (tempx);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (temprc);
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_get_x (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_ILLlp_cache * C,
+ EGLPNUM_TYPE * x)
+{
+ int rval = 0;
+
+ rval = EGLPNUM_TYPENAME_ILLlib_solution (lp, C, 0, x, 0, 0, 0);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_get_slack (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_ILLlp_cache * C,
+ EGLPNUM_TYPE * slack)
+{
+ int rval = 0;
+
+ rval = EGLPNUM_TYPENAME_ILLlib_solution (lp, C, 0, 0, 0, slack, 0);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+
+int EGLPNUM_TYPENAME_ILLlib_objval (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_ILLlp_cache * C,
+ EGLPNUM_TYPE * val)
+{
+ int rval = 0;
+
+ if (lp->basisstat.optimal)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlib_solution (lp, C, val, 0, 0, 0, 0);
+ CHECKRVALG (rval, CLEANUP);
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (*val, lp->dobjval); /* Ask Sanjeeb */
+ }
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_tableau (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int row,
+ EGLPNUM_TYPE * binv,
+ EGLPNUM_TYPE * tabrow)
+{
+ int rval = 0;
+ int i;
+ int ncols = lp->O->ncols;
+ int nrows = lp->O->nrows;
+ int nstruct = lp->O->nstruct;
+ EGLPNUM_TYPE *brow = 0;
+ EGLPNUM_TYPE *trow = 0;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp = lp->O;
+
+ if (row < 0 || row >= qslp->nrows)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_tableau called with bad row: %d", row);
+ rval = 1;
+ ILL_CLEANUP;
+ }
+ brow = EGLPNUM_TYPENAME_EGlpNumAllocArray (nrows);
+
+ if (tabrow)
+ trow = EGLPNUM_TYPENAME_EGlpNumAllocArray (ncols);
+
+ rval = EGLPNUM_TYPENAME_ILLbasis_tableau_row (lp, row, brow, trow, 0, 0);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (binv)
+ {
+ for (i = 0; i < nrows; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (binv[i], brow[i]);
+ }
+ }
+
+ if (tabrow)
+ {
+ for (i = 0; i < nstruct; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (tabrow[i], trow[qslp->structmap[i]]);
+ }
+ for (i = 0; i < nrows; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (tabrow[nstruct + i], trow[qslp->rowmap[i]]);
+ }
+ }
+
+CLEANUP:
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (brow);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (trow);
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_basis_order (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int *header)
+{
+ int rval = 0;
+ int i, j;
+ int ncols = lp->O->ncols;
+ int nrows = lp->O->nrows;
+ int nstruct = lp->O->nstruct;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp = lp->O;
+ int *invmap = 0;
+
+ ILL_SAFE_MALLOC (invmap, ncols, int);
+
+ for (j = 0; j < nstruct; j++)
+ {
+ invmap[qslp->structmap[j]] = j;
+ }
+ for (i = 0; i < nrows; i++)
+ {
+ invmap[qslp->rowmap[i]] = nstruct + i;
+ }
+
+ for (i = 0; i < nrows; i++)
+ {
+ header[i] = invmap[lp->baz[i]];
+ }
+
+CLEANUP:
+
+ ILL_IFFREE (invmap, int);
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_chgbnd (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int indx,
+ int lu,
+ const EGLPNUM_TYPE bnd)
+{
+ int rval = 0;
+ int col;
+
+ if (!lp)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_chgbnd called without an lp");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ if (indx < 0 || indx > lp->O->nstruct)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_chgbnd called with bad indx: %d", indx);
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ if (lp->O->sinfo)
+ { /* Presolve LP is no longer valid, free the data */
+ EGLPNUM_TYPENAME_ILLlp_sinfo_free (lp->O->sinfo);
+ ILL_IFFREE (lp->O->sinfo, EGLPNUM_TYPENAME_ILLlp_sinfo);
+ }
+
+ col = lp->O->structmap[indx];
+
+ switch (lu)
+ {
+ case 'L':
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->O->lower[col], bnd);
+ break;
+ case 'U':
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->O->upper[col], bnd);
+ break;
+ case 'B':
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->O->lower[col], bnd);
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->O->upper[col], bnd);
+ break;
+ default:
+ QSlog("EGLPNUM_TYPENAME_ILLlib_chgbnd called with lu: %c", lu);
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_chgbnds (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int cnt,
+ int *indx,
+ char *lu,
+ const EGLPNUM_TYPE * bnd)
+{
+ int rval = 0;
+ int i;
+
+ for (i = 0; i < cnt; i++)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, indx[i], lu[i], bnd[i]);
+ if (rval)
+ ILL_CLEANUP;
+ }
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_getbnd (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int indx,
+ int lu,
+ EGLPNUM_TYPE * bnd)
+{
+ int rval = 0;
+ int col;
+
+ if (!lp)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_getbnd called without an lp");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ if (indx < 0 || indx > lp->O->nstruct)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_getbnd called with bad indx: %d", indx);
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ col = lp->O->structmap[indx];
+
+ switch (lu)
+ {
+ case 'L':
+ EGLPNUM_TYPENAME_EGlpNumCopy (*bnd, lp->O->lower[col]);
+ break;
+ case 'U':
+ EGLPNUM_TYPENAME_EGlpNumCopy (*bnd, lp->O->upper[col]);
+ break;
+ default:
+ QSlog("EGLPNUM_TYPENAME_ILLlib_getbnd called with lu: %c", lu);
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_getbnds_list (
+ EGLPNUM_TYPENAME_lpinfo *lp,
+ int num,
+ int*collist,
+ EGLPNUM_TYPE *lower,
+ EGLPNUM_TYPE *upper)
+{
+ int rval = 0;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp;
+ int nstruct;
+ int j, col;
+
+ if (!lp) {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_getbnds_list called without an lp");
+ rval = 1; ILL_CLEANUP;
+ }
+
+ qslp = lp->O;
+ nstruct = qslp->nstruct;
+ for (j = 0; j < num ; j++) {
+ if(collist[j]<0|| collist[j] >= nstruct)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_getbnds_list collist[%d] = %d out "
+ "of range", j, collist[j]);
+ }
+ col = qslp->structmap[collist[j]];
+ if (lower)
+ EGLPNUM_TYPENAME_EGlpNumCopy(lower[j], qslp->lower[col]);
+ if (upper)
+ EGLPNUM_TYPENAME_EGlpNumCopy(upper[j], qslp->upper[col]);
+ }
+
+CLEANUP:
+
+ EG_RETURN(rval);
+}
+
+
+int EGLPNUM_TYPENAME_ILLlib_getbnds (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPE * lower,
+ EGLPNUM_TYPE * upper)
+{
+ int rval = 0;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp;
+ int nstruct;
+ int j, col;
+
+ if (!lp)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_getbnd called without an lp");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ qslp = lp->O;
+ nstruct = qslp->nstruct;
+
+ for (j = 0; j < nstruct; j++)
+ {
+ col = qslp->structmap[j];
+ if (lower)
+ EGLPNUM_TYPENAME_EGlpNumCopy (lower[j], qslp->lower[col]);
+ if (upper)
+ EGLPNUM_TYPENAME_EGlpNumCopy (upper[j], qslp->upper[col]);
+ }
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_strongbranch (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * pinf,
+ int *candidatelist,
+ int ncand,
+ EGLPNUM_TYPE * xlist,
+ EGLPNUM_TYPE * downpen,
+ EGLPNUM_TYPE * uppen,
+ int iterations,
+ EGLPNUM_TYPE objbound,
+ itcnt_t*itcnt)
+{
+ int rval = 0;
+ int i, k, status, have_norms;
+ int olditer = lp->maxiter;
+ int nstruct = lp->O->nstruct;
+ int nrows = lp->O->nrows;
+ EGLPNUM_TYPE *myx = 0;
+ EGLPNUM_TYPE xi, t, oldbnd;
+ EGLPNUM_TYPENAME_price_info lpinf;
+ EGLPNUM_TYPENAME_ILLlp_basis B, origB;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (lpinf.htrigger);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (xi);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (t);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (oldbnd);
+ EGLPNUM_TYPENAME_EGlpNumZero (oldbnd);
+ EGLPNUM_TYPENAME_ILLlp_basis_init (&B);
+ EGLPNUM_TYPENAME_ILLlp_basis_init (&origB);
+ EGLPNUM_TYPENAME_ILLprice_init_pricing_info (&lpinf);
+ lpinf.dI_price = QS_PRICE_DSTEEP;
+ lpinf.dII_price = QS_PRICE_DSTEEP;
+
+ if (xlist == 0)
+ {
+ myx = EGLPNUM_TYPENAME_EGlpNumAllocArray (nstruct);
+ rval = EGLPNUM_TYPENAME_ILLlib_get_x (lp, 0, myx);
+ CHECKRVALG (rval, CLEANUP);
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLlp_basis_alloc (&origB, nstruct, nrows);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_getbasis (lp, origB.cstat, origB.rstat);
+ CHECKRVALG (rval, CLEANUP);
+
+ check_pinf (pinf, &have_norms);
+ if (have_norms == 0)
+ {
+ origB.rownorms = EGLPNUM_TYPENAME_EGlpNumAllocArray (nrows);
+ rval = EGLPNUM_TYPENAME_ILLlib_getrownorms (lp, pinf, origB.rownorms);
+ CHECKRVALG (rval, CLEANUP);
+ }
+ else
+ {
+ lp->basisid = -1;
+ rval = EGLPNUM_TYPENAME_ILLlib_optimize (lp, 0, &lpinf, DUAL_SIMPLEX, &status, 0, itcnt);
+ CHECKRVALG (rval, CLEANUP);
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLlp_basis_alloc (&B, nstruct, nrows); /* Note: B and orgiB may */
+ /* differ. */
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_getbasis (lp, B.cstat, B.rstat);
+ CHECKRVALG (rval, CLEANUP);
+ B.rownorms = EGLPNUM_TYPENAME_EGlpNumAllocArray (nrows);
+
+ if (have_norms == 0)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlib_getrownorms (lp, pinf, B.rownorms);
+ CHECKRVALG (rval, CLEANUP);
+ }
+ else
+ {
+ rval = EGLPNUM_TYPENAME_ILLlib_getrownorms (lp, &lpinf, B.rownorms);
+ CHECKRVALG (rval, CLEANUP);
+ }
+
+ lp->maxiter = iterations;
+
+ for (i = 0; i < ncand; i++)
+ {
+ k = candidatelist[i];
+ rval = EGLPNUM_TYPENAME_ILLlib_getbnd (lp, k, 'U', &oldbnd);
+ CHECKRVALG (rval, CLEANUP);
+ if (xlist)
+ EGLPNUM_TYPENAME_EGlpNumCopy (xi, xlist[i]);
+ else
+ EGLPNUM_TYPENAME_EGlpNumCopy (xi, myx[k]);
+ EGLPNUM_TYPENAME_EGlpNumFloor (t, xi);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessDbl (t, 0.1) && EGLPNUM_TYPENAME_EGlpNumIsGreaDbl (t, -0.1))
+ EGLPNUM_TYPENAME_EGlpNumZero (t);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, k, 'U', t);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_optimize (lp, &B, &lpinf, DUAL_SIMPLEX, &status, 0, itcnt);
+ CHECKRVALG (rval, CLEANUP);
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (downpen[i], lp->dobjval);
+ rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, k, 'U', oldbnd);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_getbnd (lp, k, 'L', &oldbnd);
+ CHECKRVALG (rval, CLEANUP);
+ EGLPNUM_TYPENAME_EGlpNumCeil (t, xi);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessDbl (t, 1.1) && EGLPNUM_TYPENAME_EGlpNumIsGreaDbl (t, 0.9))
+ EGLPNUM_TYPENAME_EGlpNumOne (t);
+ rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, k, 'L', t);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_optimize (lp, &B, &lpinf, DUAL_SIMPLEX, &status, 0, itcnt);
+ CHECKRVALG (rval, CLEANUP);
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (uppen[i], lp->dobjval);
+ rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (lp, k, 'L', oldbnd);
+ CHECKRVALG (rval, CLEANUP);
+ }
+
+ if (lp->O->objsense == EGLPNUM_TYPENAME_ILL_MAX)
+ {
+
+ }
+ else
+ {
+ for (i = 0; i < ncand; i++)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (objbound, downpen[i]))
+ EGLPNUM_TYPENAME_EGlpNumCopy (downpen[i], objbound);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (objbound, uppen[i]))
+ EGLPNUM_TYPENAME_EGlpNumCopy (uppen[i], objbound);
+ }
+ }
+
+ /* Restore the old optimal solution */
+
+ lp->maxiter = olditer;
+ rval = EGLPNUM_TYPENAME_ILLlib_optimize (lp, &origB, pinf, DUAL_SIMPLEX, &status, 0, itcnt);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EGLPNUM_TYPENAME_EGlpNumClearVar (xi);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (t);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (oldbnd);
+ lp->maxiter = olditer;
+ EGLPNUM_TYPENAME_ILLprice_free_pricing_info (&lpinf);
+ EGLPNUM_TYPENAME_ILLlp_basis_free (&B);
+ EGLPNUM_TYPENAME_ILLlp_basis_free (&origB);
+ if (xlist == 0)
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (myx);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (lpinf.htrigger);
+ EG_RETURN (rval);
+}
+
+#define EXTRA_ROWS (100)
+#define EXTRA_COLS (100)
+#define EXTRA_MAT (1000)
+
+int EGLPNUM_TYPENAME_ILLlib_newrow (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_ILLlp_basis * B,
+ const EGLPNUM_TYPE rhs,
+ int sense,
+ const EGLPNUM_TYPE range,
+ const char *name)
+{
+ int rval = 0;
+
+ rval = EGLPNUM_TYPENAME_ILLlib_addrow (lp, B, 0, 0, 0, rhs, sense, range, name);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_newrows (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_ILLlp_basis * B,
+ int num,
+ const EGLPNUM_TYPE * rhs,
+ char *sense,
+ const EGLPNUM_TYPE * range,
+ const char **names)
+{
+ int rval = 0;
+ int *rmatcnt = 0;
+ int *rmatbeg = 0;
+ int i;
+
+ if (!num)
+ ILL_CLEANUP;
+
+ ILL_SAFE_MALLOC (rmatcnt, num, int);
+
+ ILL_SAFE_MALLOC (rmatbeg, num, int);
+
+ for (i = 0; i < num; i++)
+ {
+ rmatcnt[i] = 0;
+ rmatbeg[i] = 0;
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLlib_addrows (lp, B, num, rmatcnt, rmatbeg, 0, 0, rhs, sense,
+ range, names, 0);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ ILL_IFFREE (rmatcnt, int);
+ ILL_IFFREE (rmatbeg, int);
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_addrows (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_ILLlp_basis * B,
+ int num,
+ int *rmatcnt,
+ int *rmatbeg,
+ int *rmatind,
+ const EGLPNUM_TYPE * rmatval,
+ const EGLPNUM_TYPE * rhs,
+ char *sense,
+ const EGLPNUM_TYPE * range,
+ const char **names,
+ int *factorok)
+{
+ int rval = 0;
+ int i, j, total, bsing;
+ int *imap = 0;
+ int *bbeg = 0;
+ int *bcnt = 0;
+ int *bindi = 0;
+ int *rindi = 0;
+ int *jstat = 0;
+ EGLPNUM_TYPE *bval = 0;
+ EGLPNUM_TYPE rng;
+ int badfactor = 0;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (rng);
+
+ if (B == 0 || B->rownorms == 0)
+ {
+ if (factorok)
+ *factorok = 0;
+ }
+
+ if (B)
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (B->colnorms);
+
+ if (B && B->rownorms && factorok && *factorok == 1)
+ {
+ int *structmap = lp->O->structmap;
+
+ lp->matbeg = lp->O->A.matbeg;
+ lp->matcnt = lp->O->A.matcnt;
+ lp->matind = lp->O->A.matind;
+ lp->matval = lp->O->A.matval;
+
+ lp->nrows = lp->O->nrows;
+ lp->ncols = lp->O->ncols;
+ if (B->rownorms_size < lp->O->nrows + num)
+ EGLPNUM_TYPENAME_EGlpNumReallocArray (&(B->rownorms), lp->O->nrows + num);
+
+ ILL_SAFE_MALLOC (bcnt, num, int);
+ ILL_SAFE_MALLOC (bbeg, num, int);
+ ILL_SAFE_MALLOC (imap, lp->O->nstruct, int);
+
+ ILL_SAFE_MALLOC (jstat, lp->ncols, int);
+
+ for (i = 0; i < lp->ncols; i++)
+ {
+ jstat[i] = -1;
+ }
+ for (i = 0; i < lp->O->nstruct; i++)
+ {
+ jstat[structmap[i]] = i;
+ }
+
+ for (i = 0; i < lp->O->nstruct; i++)
+ {
+ imap[i] = -1;
+ }
+ for (i = 0; i < lp->O->nrows; i++)
+ {
+ if (jstat[lp->baz[i]] != -1)
+ {
+ imap[jstat[lp->baz[i]]] = i;
+ }
+ }
+
+ for (i = 0, total = 0; i < num; i++)
+ {
+ bcnt[i] = 0;
+ bbeg[i] = total;
+ for (j = 0; j < rmatcnt[i]; j++)
+ {
+ if (imap[rmatind[rmatbeg[i] + j]] != -1)
+ {
+ bcnt[i]++;
+ total++;
+ }
+ }
+ }
+ if (total)
+ {
+ ILL_SAFE_MALLOC (bindi, total, int);
+
+ bval = EGLPNUM_TYPENAME_EGlpNumAllocArray (total);
+ }
+ for (i = 0, total = 0; i < num; i++)
+ {
+ for (j = 0; j < rmatcnt[i]; j++)
+ {
+ if (imap[rmatind[rmatbeg[i] + j]] != -1)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (bval[total], rmatval[rmatbeg[i] + j]);
+ bindi[total] = imap[rmatind[rmatbeg[i] + j]];
+ total++;
+ }
+ }
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLprice_get_new_rownorms (lp, num, B->rownorms + lp->O->nrows,
+ bcnt, bbeg, bindi, bval);
+ CHECKRVALG (rval, CLEANUP);
+
+ ILL_IFFREE (bcnt, int);
+ ILL_IFFREE (bbeg, int);
+ ILL_IFFREE (bindi, int);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (bval);
+ ILL_IFFREE (imap, int);
+
+ badfactor = 1;
+ }
+
+ for (i = 0; i < num; i++)
+ {
+ if (range)
+ EGLPNUM_TYPENAME_EGlpNumCopy (rng, range[i]);
+ else
+ EGLPNUM_TYPENAME_EGlpNumZero (rng);
+ if (names)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlib_addrow (lp, B, rmatcnt[i], rmatind + rmatbeg[i],
+ rmatval + rmatbeg[i], rhs[i], sense[i], rng,
+ names[i]);
+ }
+ else
+ {
+ rval = EGLPNUM_TYPENAME_ILLlib_addrow (lp, B, rmatcnt[i], rmatind + rmatbeg[i],
+ rmatval + rmatbeg[i], rhs[i], sense[i], rng, 0);
+ }
+ CHECKRVALG (rval, CLEANUP);
+ }
+
+
+ if (B && B->rownorms && (factorok && *factorok == 0))
+ {
+ lp->matbeg = lp->O->A.matbeg;
+ lp->matcnt = lp->O->A.matcnt;
+ lp->matind = lp->O->A.matind;
+ lp->matval = lp->O->A.matval;
+ lp->nrows = lp->O->nrows;
+ lp->ncols = lp->O->ncols;
+ lp->bz = lp->O->rhs;
+ lp->nnbasic = lp->ncols - lp->nrows;
+
+ rval = EGLPNUM_TYPENAME_ILLbasis_load (lp, B);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (lp->f)
+ EGLPNUM_TYPENAME_ILLfactor_free_factor_work (lp->f);
+
+ rval = EGLPNUM_TYPENAME_ILLbasis_factor (lp, &bsing);
+ CHECKRVALG (rval, CLEANUP);
+ if (bsing)
+ MESSAGE (__QS_SB_VERB, "Singular Basis found!");
+ *factorok = 1;
+
+ if (B->rownorms_size < lp->O->nrows)
+ EGLPNUM_TYPENAME_EGlpNumReallocArray (&(B->rownorms), lp->O->nrows);
+
+ ILL_SAFE_MALLOC (rindi, lp->O->nrows /* num */ , int);
+
+ for (i = 0; i < num; i++)
+ {
+ rindi[i] = lp->O->nrows - num + i;
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLprice_get_dsteep_norms (lp, num, rindi,
+ B->rownorms + lp->O->nrows - num);
+ CHECKRVALG (rval, CLEANUP);
+ }
+
+ if (factorok != 0 && badfactor == 1)
+ {
+ *factorok = 0;
+ }
+
+
+CLEANUP:
+
+ ILL_IFFREE (bcnt, int);
+ ILL_IFFREE (bbeg, int);
+ ILL_IFFREE (bindi, int);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (bval);
+ ILL_IFFREE (imap, int);
+ ILL_IFFREE (jstat, int);
+ ILL_IFFREE (rindi, int);
+
+ EGLPNUM_TYPENAME_EGlpNumClearVar (rng);
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_addrow (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_ILLlp_basis * B,
+ int cnt,
+ int *ind,
+ const EGLPNUM_TYPE * val,
+ const EGLPNUM_TYPE rhs,
+ int sense,
+ const EGLPNUM_TYPE range,
+ const char *name)
+{
+ int rval = 0;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp;
+ EGLPNUM_TYPENAME_ILLmatrix *A;
+ int i, nrows, ncols;
+ char buf[ILL_namebufsize];
+ int tind[1];
+ EGLPNUM_TYPE tval[1];
+ int *tempind = 0;
+ int pind, hit;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (tval[0]);
+
+ if (!lp)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_addrow called without an lp");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ qslp = lp->O;
+ A = &qslp->A;
+
+ if (qslp->rA)
+ { /* After an addrow call, needs to be updated */
+ EGLPNUM_TYPENAME_ILLlp_rows_clear (qslp->rA);
+ ILL_IFFREE (qslp->rA, EGLPNUM_TYPENAME_ILLlp_rows);
+ }
+
+ if (qslp->sinfo)
+ { /* Presolve LP is no longer valid, free the data */
+ EGLPNUM_TYPENAME_ILLlp_sinfo_free (qslp->sinfo);
+ ILL_IFFREE (qslp->sinfo, EGLPNUM_TYPENAME_ILLlp_sinfo);
+ }
+
+ nrows = qslp->nrows;
+ ncols = qslp->ncols;
+
+ /* If the row has a range, create the rangeval array if needed */
+
+ if (sense == 'R' && !(qslp->rangeval) && qslp->rowsize > 0)
+ {
+ qslp->rangeval = EGLPNUM_TYPENAME_EGlpNumAllocArray (qslp->rowsize);
+ for (i = 0; i < qslp->nrows; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumZero (qslp->rangeval[i]);
+ }
+ }
+
+ /* Add the row to the row structures */
+
+ if (qslp->rowsize < nrows + 1)
+ {
+ EGLPNUM_TYPENAME_EGlpNumReallocArray (&(qslp->rhs), qslp->rowsize + EXTRA_ROWS);
+ qslp->sense = EGrealloc (qslp->sense,
+ sizeof (char) * (qslp->rowsize + EXTRA_ROWS));
+ //rval = ILLutil_reallocrus_count ((void **) &(qslp->sense),
+ // qslp->rowsize + EXTRA_ROWS, sizeof (char));
+ //CHECKRVALG(rval,CLEANUP);
+
+ qslp->rowmap = EGrealloc (qslp->rowmap,
+ sizeof (int) * (qslp->rowsize + EXTRA_ROWS));
+ //rval = ILLutil_reallocrus_count ((void **) &(qslp->rowmap),
+ // qslp->rowsize + EXTRA_ROWS, sizeof (int));
+ //CHECKRVALG(rval,CLEANUP);
+
+ if (qslp->rangeval || sense == 'R')
+ EGLPNUM_TYPENAME_EGlpNumReallocArray (&(qslp->rangeval), qslp->rowsize + EXTRA_ROWS);
+
+ qslp->rownames = EGrealloc (qslp->rownames,
+ sizeof (char *) * (qslp->rowsize + EXTRA_ROWS));
+ //rval = ILLutil_reallocrus_count ((void **) &(qslp->rownames),
+ // qslp->rowsize + EXTRA_ROWS,
+ // sizeof (char *));
+ //CHECKRVALG(rval,CLEANUP);
+ qslp->rowsize += EXTRA_ROWS;
+ }
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (qslp->rhs[nrows], rhs);
+ qslp->sense[nrows] = sense;
+ qslp->rowmap[nrows] = ncols; /* this will be the new logical */
+ if (qslp->rangeval)
+ {
+ if (sense == 'R')
+ EGLPNUM_TYPENAME_EGlpNumCopy (qslp->rangeval[nrows], range);
+ else
+ EGLPNUM_TYPENAME_EGlpNumZero (qslp->rangeval[nrows]);
+ }
+ ILL_FAILtrue (qslp->rownames == NULL, "must always be non NULL");
+ EGLPNUM_TYPENAME_ILLlib_findName (qslp, 1 /*row */ , name, nrows, buf);
+ ILL_UTIL_STR (qslp->rownames[nrows], buf);
+ ILLsymboltab_register (&qslp->rowtab, buf, qslp->nrows, &pind, &hit);
+ ILL_FAILfalse (hit == 0, "must be new");
+
+
+ /* Add the logical variable to the column structures */
+
+ if (qslp->colsize < ncols + 1)
+ {
+ EGLPNUM_TYPENAME_EGlpNumReallocArray (&(qslp->lower), qslp->colsize + EXTRA_COLS);
+ EGLPNUM_TYPENAME_EGlpNumReallocArray (&(qslp->upper), qslp->colsize + EXTRA_COLS);
+ EGLPNUM_TYPENAME_EGlpNumReallocArray (&(qslp->obj), qslp->colsize + EXTRA_COLS);
+ qslp->colsize += EXTRA_COLS;
+ }
+
+ EGLPNUM_TYPENAME_EGlpNumZero (qslp->obj[ncols]);
+ EGLPNUM_TYPENAME_EGlpNumZero (qslp->lower[ncols]);
+ if (sense == 'E')
+ {
+ EGLPNUM_TYPENAME_EGlpNumZero (qslp->upper[ncols]); /* Artificial */
+ }
+ else if (sense == 'R')
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (qslp->upper[ncols], range); /* Range */
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (qslp->upper[ncols], EGLPNUM_TYPENAME_ILL_MAXDOUBLE); /* Slack */
+ }
+
+ /* Add new row and new logical col to matrix */
+
+ /* Need to map the structural indices to their proper place */
+
+ if (cnt)
+ {
+ ILL_SAFE_MALLOC (tempind, cnt, int);
+
+ for (i = 0; i < cnt; i++)
+ {
+ tempind[i] = qslp->structmap[ind[i]];
+ }
+ }
+
+ rval = matrix_addrow (A, cnt, tempind, val);
+ CHECKRVALG (rval, CLEANUP);
+
+ tind[0] = nrows;
+ EGLPNUM_TYPENAME_EGlpNumOne (*tval);
+ if (sense == 'G' || sense == 'R')
+ EGLPNUM_TYPENAME_EGlpNumSign (*tval);
+
+ rval = matrix_addcol (A, 1, tind, tval);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (B != 0)
+ {
+ B->rstat = EGrealloc (B->rstat, sizeof (char) * (nrows + 1));
+ //rval = ILLutil_reallocrus_count ((void **) &(B->rstat), nrows + 1,
+ // sizeof (char));
+ //CHECKRVALG(rval,CLEANUP);
+ B->rstat[nrows] = QS_ROW_BSTAT_BASIC;
+ }
+
+#if 0
+ lp->basisid = -1; /* To get optimizer to reload the basis */
+#endif
+
+ qslp->ncols++;
+ qslp->nrows++;
+ qslp->nzcount += (cnt + 1);
+
+ if (B != 0)
+ {
+ B->nrows++;
+ }
+
+CLEANUP:
+ ILL_IFFREE (tempind, int);
+
+ EGLPNUM_TYPENAME_EGlpNumClearVar (tval[0]);
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_delrows (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_ILLlp_basis * B,
+ EGLPNUM_TYPENAME_ILLlp_cache * C,
+ int num,
+ int *dellist,
+ int *basis_ok,
+ int *cache_ok)
+{
+ int rval = 0;
+ int i, j, k, nrows, ncols, nstruct, spot, dk, bok = 0, cok = 0;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp;
+ EGLPNUM_TYPENAME_ILLmatrix *A;
+ char *rowmark = 0;
+ char *colmark = 0;
+ int *newrowindex = 0;
+ int *newcolindex = 0;
+ int *ind, *beg, *cnt;
+ EGLPNUM_TYPE *val;
+
+ if (!lp)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_delrows called without an lp");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ if (num <= 0)
+ {
+ if (basis_ok)
+ *basis_ok = 1;
+ if (cache_ok)
+ *cache_ok = 1;
+ ILL_CLEANUP;
+ }
+
+ if (basis_ok)
+ *basis_ok = 0;
+ if (cache_ok)
+ *cache_ok = 0;
+
+ qslp = lp->O;
+ A = &qslp->A;
+
+ if (qslp->rA)
+ { /* After a delrow call, needs to be updated */
+ EGLPNUM_TYPENAME_ILLlp_rows_clear (qslp->rA);
+ ILL_IFFREE (qslp->rA, EGLPNUM_TYPENAME_ILLlp_rows);
+ }
+
+ nrows = A->matrows;
+ ncols = A->matcols;
+ ind = A->matind;
+ beg = A->matbeg;
+ cnt = A->matcnt;
+ val = A->matval;
+ nstruct = qslp->nstruct;
+
+ ILL_SAFE_MALLOC (rowmark, nrows, char);
+
+ for (i = 0; i < nrows; i++)
+ {
+ rowmark[i] = 0;
+ }
+ for (i = 0; i < num; i++)
+ {
+ rowmark[dellist[i]] = 1;
+ }
+
+
+ /* Try to update the basis */
+
+ if (B)
+ {
+ bok = 1;
+ cok = 1;
+ for (i = 0; i < num; i++)
+ {
+ j = dellist[i];
+ if (B->rstat[j] == QS_ROW_BSTAT_LOWER ||
+ B->rstat[j] == QS_ROW_BSTAT_UPPER)
+ {
+ bok = 0;
+ break;
+ }
+ if (C && EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_DFEAS_TOLER, C->pi[j]))
+ {
+/*
+ QSlog("XXXX: Postive pi (%f) at basic row", C->pi[j]);
+*/
+ cok = 0;
+ }
+ }
+ if (bok == 1)
+ {
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (B->colnorms);
+ if (B->rownorms)
+ {
+ for (i = 0, k = 0; i < nstruct; i++)
+ {
+ if (B->cstat[i] == QS_COL_BSTAT_BASIC)
+ k++;
+ }
+ for (i = 0, j = k; i < nrows; i++)
+ {
+ if (B->rstat[i] == QS_ROW_BSTAT_BASIC)
+ {
+ if (rowmark[i] == 0)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (B->rownorms[k++], B->rownorms[j]);
+ }
+ j++;
+ }
+ }
+ if (k != nrows - num)
+ {
+ QSlog("error in EGLPNUM_TYPENAME_ILLlib_delrows");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+ }
+
+ for (i = 0, j = 0; i < nrows; i++)
+ {
+ if (rowmark[i] == 0)
+ {
+ B->rstat[j++] = B->rstat[i];
+ }
+ }
+ B->nrows = j;
+
+ if (C && cok == 1)
+ {
+ for (i = 0, j = 0; i < nrows; i++)
+ {
+ if (rowmark[i] == 0)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (C->pi[j], C->pi[i]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (C->slack[j++], C->slack[i]);
+ }
+ }
+ C->nrows = j;
+ if (cache_ok)
+ *cache_ok = 1;
+ }
+ if (basis_ok)
+ *basis_ok = 1;
+ }
+ }
+
+ ILL_SAFE_MALLOC (newrowindex, nrows, int);
+
+
+ /* Delete the marked rows */
+
+ ILL_FAILtrue (qslp->rownames == NULL, "must always be non NULL");
+ for (i = 0, j = 0; i < nrows; i++)
+ {
+ if (rowmark[i] == 0)
+ {
+ if (i != j)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (qslp->rhs[j], qslp->rhs[i]);
+ qslp->sense[j] = qslp->sense[i];
+ if (qslp->rangeval)
+ EGLPNUM_TYPENAME_EGlpNumCopy (qslp->rangeval[j], qslp->rangeval[i]);
+ if (qslp->rownames)
+ qslp->rownames[j] = qslp->rownames[i];
+ }
+ newrowindex[i] = j++;
+ }
+ else
+ {
+ if (qslp->rownames)
+ {
+ rval = ILLsymboltab_delete (&qslp->rowtab, qslp->rownames[i]);
+ CHECKRVALG (rval, CLEANUP);
+ ILL_IFFREE (qslp->rownames[i], char);
+ }
+ }
+ }
+
+
+ /* Delete the logicals */
+
+ ILL_SAFE_MALLOC (colmark, ncols, char);
+
+ for (i = 0; i < ncols; i++)
+ {
+ colmark[i] = 0;
+ }
+ for (i = 0; i < num; i++)
+ {
+ colmark[qslp->rowmap[dellist[i]]] = 1;
+ }
+
+ rval = delcols_work (lp, colmark);
+ CHECKRVALG (rval, CLEANUP);
+
+ A->matcols -= num;
+ qslp->ncols -= num;
+
+
+ /* Pack the rowmap */
+
+ for (i = 0, j = 0; i < nrows; i++)
+ {
+ if (rowmark[i] == 0)
+ {
+ qslp->rowmap[j++] = qslp->rowmap[i];
+ }
+ }
+
+ /* Remove the entries to deleted rows, and update the indices */
+
+ for (i = 0; i < ncols - num; i++)
+ {
+ dk = 0;
+ spot = beg[i];
+ for (j = 0; j < cnt[i]; j++)
+ {
+ if (rowmark[ind[beg[i] + j]] == 1)
+ {
+ dk++;
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (val[spot], val[beg[i] + j]);
+ ind[spot] = newrowindex[ind[beg[i] + j]];
+ spot++;
+ }
+ }
+ for (; spot < beg[i] + cnt[i]; spot++)
+ {
+ ind[spot] = -1;
+ }
+
+ cnt[i] -= dk;
+ if (cnt[i] == 0)
+ {
+ ind[beg[i]] = 1; /* we always mark the empty cols */
+ }
+ }
+
+ A->matrows -= num;
+ qslp->nrows -= num;
+
+#if 0
+ lp->basisid = -1; /* To get optimizer to reload the basis */
+#endif
+
+ /* if the base is OK, we MUST load the status variables again */
+ if(bok)
+ {
+ rval = EGLPNUM_TYPENAME_ILLbasis_load( lp, B);
+ CHECKRVALG (rval, CLEANUP);
+ }
+CLEANUP:
+
+ ILL_IFFREE (rowmark, char);
+ ILL_IFFREE (colmark, char);
+ ILL_IFFREE (newcolindex, int);
+ ILL_IFFREE (newrowindex, int);
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_delcols (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_ILLlp_basis * B,
+ int num,
+ int *dellist,
+ int *basis_ok)
+{
+ int rval = 0;
+ int i, j, bok = 0, ncols;
+ char *colmark = 0;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp;
+
+ if (!lp)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_delcols called without an lp");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ if (basis_ok)
+ *basis_ok = 0;
+
+ if (num <= 0)
+ {
+ *basis_ok = 1;
+ ILL_CLEANUP;
+ }
+
+ qslp = lp->O;
+ ncols = qslp->A.matcols;
+
+ if (qslp->rA)
+ { /* After a delcol call, needs to be updated */
+ EGLPNUM_TYPENAME_ILLlp_rows_clear (qslp->rA);
+ ILL_IFFREE (qslp->rA, EGLPNUM_TYPENAME_ILLlp_rows);
+ }
+
+ ILL_SAFE_MALLOC (colmark, ncols, char);
+
+ for (i = 0; i < ncols; i++)
+ {
+ colmark[i] = 0;
+ }
+ for (i = 0; i < num; i++)
+ {
+ colmark[qslp->structmap[dellist[i]]] = 1;
+ }
+
+ if (B)
+ {
+ B->nstruct -= num;
+ bok = 1;
+ for (i = 0; i < num; i++)
+ {
+ j = dellist[i];
+ if (B->cstat[j] == QS_COL_BSTAT_BASIC)
+ {
+ bok = 0;
+ //QSlog("BONG");
+ break;
+ }
+ }
+ if (bok == 1)
+ {
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (B->colnorms);
+ for (i = 0, j = 0; i < qslp->nstruct; i++)
+ {
+ if (colmark[qslp->structmap[i]] == 0)
+ {
+ B->cstat[j++] = B->cstat[i];
+ }
+ }
+ if (basis_ok)
+ *basis_ok = 1;
+ }
+ }
+
+ rval = delcols_work (lp, colmark);
+ CHECKRVALG (rval, CLEANUP);
+
+
+ qslp->A.matcols -= num;
+ qslp->ncols -= num;
+ qslp->nstruct -= num;
+
+ /* if the base is OK, we MUST load the status variables again */
+ if(bok)
+ {
+ rval = EGLPNUM_TYPENAME_ILLbasis_load( lp, B);
+ CHECKRVALG (rval, CLEANUP);
+ }
+#if 0
+ lp->basisid = -1; /* To get optimizer to reload the basis */
+#endif
+
+CLEANUP:
+
+ ILL_IFFREE (colmark, char);
+
+ EG_RETURN (rval);
+}
+
+static int matrix_getcoef (
+ EGLPNUM_TYPENAME_ILLmatrix *A,
+ int row,
+ int col,
+ EGLPNUM_TYPE*val)
+{
+ int i;
+ int rval = 0;
+ if (row >= A->matrows || row < 0)
+ {
+ QSlog("illegal row index in matrix_getcoef");
+ rval= 1;
+ ILL_CLEANUP;
+ }
+
+ if (col >= A->matcols || col < 0)
+ {
+ QSlog("illegal col index in matrix_getcoef");
+ rval= 1;
+ ILL_CLEANUP;
+ }
+
+ /* by default value is zero */
+ EGLPNUM_TYPENAME_EGlpNumZero(*val);
+ for (i = A->matbeg[col]; i < A->matbeg[col] + A->matcnt[col]; i++)
+ {
+ if (A->matind[i] == row)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy(*val, A->matval[i]);
+ ILL_CLEANUP;
+ }
+ }
+
+CLEANUP:
+
+ EG_RETURN(rval);
+}
+
+static int delcols_work (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ char *colmark)
+{
+ int rval = 0;
+ int i, j, k, nrows, ncols;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp;
+ EGLPNUM_TYPENAME_ILLmatrix *A;
+ int *newcolindex = 0;
+ int *ind, *beg, *cnt;
+
+ /* Allows logicals to be deleted, to handle call from delcols. */
+
+ qslp = lp->O;
+ A = &qslp->A;
+ nrows = A->matrows;
+ ncols = A->matcols;
+ ind = A->matind;
+ beg = A->matbeg;
+ cnt = A->matcnt;
+
+ ILL_SAFE_MALLOC (newcolindex, ncols, int);
+
+ /* Delete the columns */
+
+ for (i = 0, j = 0; i < ncols; i++)
+ {
+ if (colmark[i] == 0)
+ {
+ if (i != j)
+ {
+ beg[j] = beg[i];
+ cnt[j] = cnt[i];
+ EGLPNUM_TYPENAME_EGlpNumCopy (qslp->obj[j], qslp->obj[i]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (qslp->lower[j], qslp->lower[i]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (qslp->upper[j], qslp->upper[i]);
+ }
+ newcolindex[i] = j++;
+ }
+ else
+ {
+ for (k = 0; k < cnt[i]; k++)
+ {
+ ind[beg[i] + k] = -1;
+ }
+ newcolindex[i] = -1;
+ }
+ }
+
+ /* Update the struct arrays */
+
+ for (i = 0, j = 0; i < qslp->nstruct; i++)
+ {
+ k = qslp->structmap[i];
+ if (colmark[k] == 0)
+ {
+ qslp->structmap[j] = newcolindex[k];
+ qslp->colnames[j] = qslp->colnames[i];
+ if (qslp->intmarker)
+ qslp->intmarker[j] = qslp->intmarker[i];
+ j++;
+ }
+ else
+ {
+ rval = ILLsymboltab_delete (&qslp->coltab, qslp->colnames[i]);
+ CHECKRVALG (rval, CLEANUP);
+ ILL_IFFREE (qslp->colnames[i], char);
+ }
+ }
+
+ /* Update the rowmap: note if logicals deleted, map will be -1 */
+
+ for (i = 0; i < nrows; i++)
+ {
+ qslp->rowmap[i] = newcolindex[qslp->rowmap[i]];
+ }
+
+CLEANUP:
+
+ ILL_IFFREE (newcolindex, int);
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_getcoef (
+ EGLPNUM_TYPENAME_lpinfo *lp,
+ int rowindex,
+ int colindex,
+ EGLPNUM_TYPE* coef)
+{
+ int rval = 0;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp;
+ EGLPNUM_TYPENAME_ILLmatrix *A;
+ int nrows, nstruct, j;
+ if (!lp)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_chgcoef called without an lp");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ qslp = lp->O;
+ A = &qslp->A;
+ nrows = qslp->nrows;
+ nstruct = qslp->nstruct;
+
+ if (rowindex < 0 || rowindex >= nrows || colindex < 0 || colindex >= nstruct)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_getcoef called with out-of-range index");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ j = qslp->structmap[colindex];
+ rval = matrix_getcoef (A, rowindex, j, coef);
+ CHECKRVALG(rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_chgcoef (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int rowindex,
+ int colindex,
+ EGLPNUM_TYPE coef)
+{
+ int rval = 0;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp;
+ EGLPNUM_TYPENAME_ILLmatrix *A;
+ int nrows, nstruct, j;
+
+ if (!lp)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_chgcoef called without an lp");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ qslp = lp->O;
+ A = &qslp->A;
+
+ nrows = qslp->nrows;
+ nstruct = qslp->nstruct;
+
+ if (rowindex < 0 || rowindex >= nrows || colindex < 0 || colindex >= nstruct)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_chgcoef called with out-of-range index");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ if (qslp->rA)
+ { /* After a chgcoef call, needs to be updated */
+ EGLPNUM_TYPENAME_ILLlp_rows_clear (qslp->rA);
+ ILL_IFFREE (qslp->rA, EGLPNUM_TYPENAME_ILLlp_rows);
+ }
+
+ if (qslp->sinfo)
+ { /* Presolve LP is no longer valid, free the data */
+ EGLPNUM_TYPENAME_ILLlp_sinfo_free (qslp->sinfo);
+ ILL_IFFREE (qslp->sinfo, EGLPNUM_TYPENAME_ILLlp_sinfo);
+ }
+
+ j = qslp->structmap[colindex];
+
+ rval = matrix_addcoef (lp, A, rowindex, j, coef);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_chgsense (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int num,
+ int *rowlist,
+ char *sense)
+{
+ int rval = 0;
+ int i, j, k;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp = lp->O;
+ EGLPNUM_TYPENAME_ILLmatrix *A = &(lp->O->A);
+
+ for (i = 0; i < num; i++)
+ {
+ j = qslp->rowmap[rowlist[i]];
+ if (A->matcnt[j] != 1)
+ {
+ QSlog("logical variable is not a singleton");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+ k = A->matbeg[j];
+ switch (sense[i])
+ {
+ case 'R': /* Range constraint, we will set its upper bound
+ once we call EGLPNUM_TYPENAME_QSchange_range, by default it
+ will be zero, i.e. an equation. */
+ qslp->sense[rowlist[i]] = 'R';
+ EGLPNUM_TYPENAME_EGlpNumZero(qslp->lower[j]);
+ EGLPNUM_TYPENAME_EGlpNumZero(qslp->upper[j]);
+ EGLPNUM_TYPENAME_EGlpNumOne(A->matval[k]);
+ break;
+ case 'E': /* Artificial */
+ qslp->sense[rowlist[i]] = 'E';
+ EGLPNUM_TYPENAME_EGlpNumZero (qslp->lower[j]);
+ EGLPNUM_TYPENAME_EGlpNumZero (qslp->upper[j]);
+ EGLPNUM_TYPENAME_EGlpNumOne (A->matval[k]);
+ break;
+ case 'G': /* Surplus */
+ qslp->sense[rowlist[i]] = 'G';
+ EGLPNUM_TYPENAME_EGlpNumZero (qslp->lower[j]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (qslp->upper[j], EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+ EGLPNUM_TYPENAME_EGlpNumOne (A->matval[k]);
+ EGLPNUM_TYPENAME_EGlpNumSign (A->matval[k]);
+ break;
+ case 'L': /* Slack */
+ qslp->sense[rowlist[i]] = 'L';
+ EGLPNUM_TYPENAME_EGlpNumZero (qslp->lower[j]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (qslp->upper[j], EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+ EGLPNUM_TYPENAME_EGlpNumOne (A->matval[k]);
+ break;
+ default:
+ QSlog("illegal sense %c in EGLPNUM_TYPENAME_ILLlib_chgsense", sense[i]);
+ rval = 1;
+ ILL_CLEANUP;
+ }
+ }
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_getsenses (
+ EGLPNUM_TYPENAME_lpinfo *lp,
+ char *senses)
+{
+ EGLPNUM_TYPENAME_ILLlpdata *qslp;
+ int nrows, i;
+ int rval = 0;
+
+ if (!lp) {
+ QSlog("ILLlib_getsense called without an LP");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ qslp = lp->O;
+ nrows = qslp->nrows;
+
+ for (i = 0; i < nrows; i++)
+ {
+ senses[i] = qslp->sense[i];
+ }
+
+CLEANUP:
+
+ EG_RETURN(rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_newcol (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_ILLlp_basis * B,
+ const EGLPNUM_TYPE obj,
+ const EGLPNUM_TYPE lower,
+ const EGLPNUM_TYPE upper,
+ const char *name,
+ int factorok)
+{
+ int rval = 0;
+
+ rval = EGLPNUM_TYPENAME_ILLlib_addcol (lp, B, 0, 0, 0, obj, lower, upper, name, factorok);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_newcols (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_ILLlp_basis * B,
+ int num,
+ EGLPNUM_TYPE * obj,
+ EGLPNUM_TYPE * lower,
+ EGLPNUM_TYPE * upper,
+ const char **names,
+ int factorok)
+{
+ int rval = 0;
+ int *cmatcnt = 0;
+ int *cmatbeg = 0;
+ int i;
+
+ ILL_SAFE_MALLOC (cmatcnt, num, int);
+
+ ILL_SAFE_MALLOC (cmatbeg, num, int);
+
+ for (i = 0; i < num; i++)
+ {
+ cmatcnt[i] = 0;
+ cmatbeg[i] = 0;
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLlib_addcols (lp, B, num, cmatcnt, cmatbeg, 0,
+ 0, obj, lower, upper, names, factorok);
+ CHECKRVALG (rval, CLEANUP);
+
+
+CLEANUP:
+
+ ILL_IFFREE (cmatcnt, int);
+ ILL_IFFREE (cmatbeg, int);
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_addcols (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_ILLlp_basis * B,
+ int num,
+ int *cmatcnt,
+ int *cmatbeg,
+ int *cmatind,
+ EGLPNUM_TYPE * cmatval,
+ EGLPNUM_TYPE * obj,
+ EGLPNUM_TYPE * lower,
+ EGLPNUM_TYPE * upper,
+ const char **names,
+ int factorok)
+{
+ int rval = 0;
+ int i;
+
+ for (i = 0; i < num; i++)
+ {
+ if (names)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlib_addcol (lp, B, cmatcnt[i], cmatind + cmatbeg[i],
+ cmatval + cmatbeg[i], obj[i], lower[i],
+ upper[i], names[i], factorok);
+ }
+ else
+ {
+ rval = EGLPNUM_TYPENAME_ILLlib_addcol (lp, B, cmatcnt[i], cmatind + cmatbeg[i],
+ cmatval + cmatbeg[i], obj[i], lower[i],
+ upper[i], 0, factorok);
+ }
+ CHECKRVALG (rval, CLEANUP);
+ }
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_addcol (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_ILLlp_basis * B,
+ int cnt,
+ int *ind,
+ EGLPNUM_TYPE * val,
+ const EGLPNUM_TYPE obj,
+ const EGLPNUM_TYPE lower,
+ const EGLPNUM_TYPE upper,
+ const char *name,
+ int factorok)
+{
+ int rval = 0;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp;
+ EGLPNUM_TYPENAME_ILLmatrix *A;
+ int ncols;
+ char buf[ILL_namebufsize];
+ int pind, hit;
+ EGLPNUM_TYPE l, u;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (l);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (u);
+
+ if (!lp)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_addcol called without an lp");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ qslp = lp->O;
+ A = &qslp->A;
+ ncols = qslp->ncols;
+
+ if (qslp->rA)
+ { /* After an addcol call, needs to be updated */
+ EGLPNUM_TYPENAME_ILLlp_rows_clear (qslp->rA);
+ ILL_IFFREE (qslp->rA, EGLPNUM_TYPENAME_ILLlp_rows);
+ }
+
+ if (qslp->sinfo)
+ { /* Presolve LP is no longer valid, free the data */
+ EGLPNUM_TYPENAME_ILLlp_sinfo_free (qslp->sinfo);
+ ILL_IFFREE (qslp->sinfo, EGLPNUM_TYPENAME_ILLlp_sinfo);
+ }
+
+
+ /* Add the new variable to the column structures */
+
+ if (qslp->colsize < ncols + 1)
+ {
+ EGLPNUM_TYPENAME_EGlpNumReallocArray (&(qslp->lower), qslp->colsize + EXTRA_COLS);
+ EGLPNUM_TYPENAME_EGlpNumReallocArray (&(qslp->upper), qslp->colsize + EXTRA_COLS);
+ EGLPNUM_TYPENAME_EGlpNumReallocArray (&(qslp->obj), qslp->colsize + EXTRA_COLS);
+ qslp->colsize += EXTRA_COLS;
+ }
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (qslp->obj[ncols], obj);
+ EGLPNUM_TYPENAME_EGlpNumCopy (qslp->lower[ncols], lower);
+ EGLPNUM_TYPENAME_EGlpNumCopy (qslp->upper[ncols], upper);
+
+ /* Add the variable to the structural arrays */
+
+ if (qslp->structsize < qslp->nstruct + 1)
+ {
+ qslp->structmap = EGrealloc (qslp->structmap,
+ sizeof (int) * (qslp->structsize +
+ EXTRA_COLS));
+ //rval = ILLutil_reallocrus_count ((void **) &(qslp->structmap),
+ // qslp->structsize + EXTRA_COLS,
+ // sizeof (int));
+ //CHECKRVALG(rval,CLEANUP);
+
+ qslp->colnames = EGrealloc (qslp->colnames,
+ sizeof (char *) * (qslp->structsize +
+ EXTRA_COLS));
+ //rval = ILLutil_reallocrus_count ((void **) &(qslp->colnames),
+ // qslp->structsize + EXTRA_COLS,
+ // sizeof (char *));
+ //CHECKRVALG(rval,CLEANUP);
+
+ if (qslp->intmarker)
+ {
+ qslp->intmarker = EGrealloc (qslp->intmarker,
+ sizeof (char) * (qslp->structsize +
+ EXTRA_COLS));
+ //rval = ILLutil_reallocrus_count ((void **) &(qslp->intmarker),
+ // qslp->structsize + EXTRA_COLS,
+ // sizeof (char));
+ //CHECKRVALG(rval,CLEANUP);
+ }
+ qslp->structsize += EXTRA_COLS;
+ }
+
+ qslp->structmap[qslp->nstruct] = ncols;
+ if (qslp->intmarker)
+ {
+ /* NOTE: If we want to add integer variables, this is the place. */
+ qslp->intmarker[qslp->nstruct] = (char) 0;
+ }
+
+ ILL_FAILtrue (qslp->colnames == NULL, "must always be non NULL");
+ EGLPNUM_TYPENAME_ILLlib_findName (qslp, 0 /*isRow */ , name, qslp->nstruct, buf);
+ ILLsymboltab_register (&qslp->coltab, buf, qslp->nstruct, &pind, &hit);
+ ILL_FAILfalse ((pind == qslp->nstruct) && (hit == 0), "must be new");
+ ILL_UTIL_STR (qslp->colnames[qslp->nstruct], buf);
+
+
+ /* Add col to the matrix */
+
+ rval = matrix_addcol (A, cnt, ind, val);
+ CHECKRVALG (rval, CLEANUP);
+
+
+ if (B)
+ {
+ B->cstat = EGrealloc (B->cstat, sizeof (char) * (qslp->nstruct + 1));
+ //rval = ILLutil_reallocrus_count ((void **) &(B->cstat),
+ // qslp->nstruct + 1, sizeof (char));
+ //CHECKRVALG(rval,CLEANUP);
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqual (lower, EGLPNUM_TYPENAME_ILL_MINDOUBLE, EGLPNUM_TYPENAME_oneLpNum) &&
+ EGLPNUM_TYPENAME_EGlpNumIsEqual (upper, EGLPNUM_TYPENAME_ILL_MAXDOUBLE, EGLPNUM_TYPENAME_oneLpNum))
+ {
+ B->cstat[qslp->nstruct] = QS_COL_BSTAT_FREE;
+ }
+ else if (EGLPNUM_TYPENAME_EGlpNumIsEqual (upper, EGLPNUM_TYPENAME_ILL_MAXDOUBLE, EGLPNUM_TYPENAME_oneLpNum))
+ {
+ B->cstat[qslp->nstruct] = QS_COL_BSTAT_LOWER;
+ }
+ //else if (lower == EGLPNUM_TYPENAME_ILL_MAXDOUBLE)
+ else if (EGLPNUM_TYPENAME_EGlpNumIsEqual (lower, EGLPNUM_TYPENAME_ILL_MAXDOUBLE, EGLPNUM_TYPENAME_oneLpNum))
+ {
+ B->cstat[qslp->nstruct] = QS_COL_BSTAT_UPPER;
+ }
+ else
+ {
+ /*l = fabs (lower);
+ * u = fabs (upper); */
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs (l, lower);
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs (u, upper);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (l, u))
+ {
+ B->cstat[qslp->nstruct] = QS_COL_BSTAT_LOWER;
+ }
+ else
+ {
+ B->cstat[qslp->nstruct] = QS_COL_BSTAT_UPPER;
+ }
+ }
+
+ /* UPDATE THE PINF PRIMAL NORMS */
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (B->colnorms);
+ }
+
+ if (factorok == 0)
+ {
+#if 0
+ lp->basisid = -1; /* To get optimizer to reload the basis */
+#endif
+ }
+ else
+ {
+ if (!lp->nbaz || !lp->vindex || !lp->vstat)
+ {
+ QSlog("ERROR: factorok set without a current basis");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ lp->nbaz = EGrealloc (lp->nbaz, sizeof (int) * (qslp->nstruct + 1));
+ //rval = ILLutil_reallocrus_count ((void **) &(lp->nbaz),
+ // qslp->nstruct + 1, sizeof (int));
+ //CHECKRVALG(rval,CLEANUP);
+
+ lp->vindex = EGrealloc (lp->vindex, sizeof (int) * (qslp->ncols + 1));
+ //rval = ILLutil_reallocrus_count ((void **) &(lp->vindex),
+ // qslp->ncols + 1, sizeof (int));
+ //CHECKRVALG(rval,CLEANUP);
+
+ lp->vstat = EGrealloc (lp->vstat, sizeof (int) * (qslp->ncols + 1));
+ //rval = ILLutil_reallocrus_count ((void **) &(lp->vstat),
+ // qslp->ncols + 1, sizeof (int));
+
+
+ lp->nbaz[qslp->nstruct] = qslp->ncols;
+ lp->vindex[qslp->ncols] = qslp->nstruct;
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqual (lower, EGLPNUM_TYPENAME_ILL_MINDOUBLE, EGLPNUM_TYPENAME_oneLpNum) &&
+ EGLPNUM_TYPENAME_EGlpNumIsEqual (upper, EGLPNUM_TYPENAME_ILL_MAXDOUBLE, EGLPNUM_TYPENAME_oneLpNum))
+ {
+ lp->vstat[qslp->ncols] = STAT_ZERO;
+ }
+ else if (EGLPNUM_TYPENAME_EGlpNumIsEqual (upper, EGLPNUM_TYPENAME_ILL_MAXDOUBLE, EGLPNUM_TYPENAME_oneLpNum))
+ {
+ lp->vstat[qslp->ncols] = STAT_LOWER;
+ }
+ //else if (lower == EGLPNUM_TYPENAME_ILL_MAXDOUBLE)
+ else if (EGLPNUM_TYPENAME_EGlpNumIsEqual (lower, EGLPNUM_TYPENAME_ILL_MAXDOUBLE, EGLPNUM_TYPENAME_oneLpNum))
+ {
+ lp->vstat[qslp->ncols] = STAT_UPPER;
+ }
+ else
+ {
+ /*l = fabs (lower);
+ * u = fabs (upper); */
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs (l, lower);
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs (u, upper);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (l, u))
+ {
+ lp->vstat[qslp->ncols] = STAT_LOWER;
+ }
+ else
+ {
+ lp->vstat[qslp->ncols] = STAT_UPPER;
+ }
+ }
+ }
+
+
+ qslp->ncols++;
+ qslp->nstruct++;
+ (qslp->nzcount) += cnt;
+
+ if (B)
+ {
+ B->nstruct++;
+ }
+
+CLEANUP:
+ EGLPNUM_TYPENAME_EGlpNumClearVar (l);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (u);
+ EG_RETURN (rval);
+}
+
+static int matrix_addrow (
+ EGLPNUM_TYPENAME_ILLmatrix * A,
+ int rowcnt,
+ int *rowind,
+ const EGLPNUM_TYPE * rowval)
+{
+ int rval = 0;
+ int i, j, k, ind, memo, stop, delta = 0;
+
+ /* matsize will be the length of the array. */
+ /* matfree will keep track of the free space at end of array. */
+
+ for (i = 0; i < rowcnt; i++)
+ {
+ if (rowind[i] >= A->matcols || rowind[i] < 0)
+ {
+ QSlog("illegal col index in matrix_addrow");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+ }
+
+ for (i = 0; i < rowcnt; i++)
+ {
+ j = rowind[i];
+ if (A->matcnt[j] > 0 &&
+ (A->matbeg[j] + A->matcnt[j] + 1 > A->matsize ||
+ A->matind[A->matbeg[j] + A->matcnt[j]] != -1))
+ {
+ delta += (A->matcnt[j] + 2); /* 1 for the new coef and 1 for */
+ /* an extra space */
+ }
+ }
+
+ if (delta < A->matfree)
+ {
+ for (i = 0; i < rowcnt; i++)
+ {
+ j = rowind[i];
+ if (A->matcnt[j] == 0)
+ {
+ A->matind[A->matbeg[j]] = A->matrows;
+ EGLPNUM_TYPENAME_EGlpNumCopy (A->matval[A->matbeg[j]], rowval[i]);
+ A->matcnt[j] = 1;
+ }
+ else if (A->matind[A->matbeg[j] + A->matcnt[j]] == -1)
+ {
+ /* Since A->matfree is positive, we know that we are not */
+ /* sitting at the end of the array. */
+ A->matind[A->matbeg[j] + A->matcnt[j]] = A->matrows;
+ EGLPNUM_TYPENAME_EGlpNumCopy (A->matval[A->matbeg[j] + A->matcnt[j]], rowval[i]);
+ if ((A->matbeg[j] + A->matcnt[j]) == (A->matsize - A->matfree))
+ {
+ A->matfree--; /* at end of used space */
+ }
+ (A->matcnt[j])++;
+ }
+ else
+ {
+ ind = A->matsize - A->matfree + 1; /* leave space for -1 */
+ memo = ind;
+ stop = A->matbeg[j] + A->matcnt[j];
+ for (k = A->matbeg[j]; k < stop; k++)
+ {
+ if (ind >= A->matsize)
+ {
+ QSlog("WHAT: %d, %d", A->matsize, ind);
+ exit (1);
+ }
+ A->matind[ind] = A->matind[k];
+ EGLPNUM_TYPENAME_EGlpNumCopy (A->matval[ind], A->matval[k]);
+ A->matind[k] = -1;
+ ind++;
+ }
+ A->matind[ind] = A->matrows;
+ EGLPNUM_TYPENAME_EGlpNumCopy (A->matval[ind], rowval[i]);
+ A->matbeg[j] = memo;
+ (A->matcnt[j])++;
+ (A->matfree) -= (A->matcnt[j] + 1);
+ }
+ }
+ }
+ else
+ {
+ rval = matrix_addrow_end (A, A->matrows, rowcnt, rowind, rowval);
+ CHECKRVALG (rval, CLEANUP);
+ }
+ A->matrows++;
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+static int matrix_addrow_end (
+ EGLPNUM_TYPENAME_ILLmatrix * A,
+ int row,
+ int rowcnt,
+ int *rowind,
+ const EGLPNUM_TYPE * rowval)
+{
+ int rval = 0;
+ int i, j, k, start, stop, total;
+ int *newbeg = 0;
+ int *newind = 0;
+ EGLPNUM_TYPE *newval = 0;
+ int ncols = A->matcols;
+
+ if (A->matcolsize > 0)
+ {
+ ILL_SAFE_MALLOC (newbeg, A->matcolsize, int);
+ }
+ ILL_SAFE_MALLOC (newind, A->matsize + rowcnt + EXTRA_MAT, int);
+
+ newval = EGLPNUM_TYPENAME_EGlpNumAllocArray (A->matsize + rowcnt + EXTRA_MAT);
+
+ A->matsize += (rowcnt + EXTRA_MAT);
+
+ for (i = 0; i < rowcnt; i++)
+ {
+ A->matcnt[rowind[i]]++;
+ }
+ for (total = 0, j = 0; j < ncols; j++)
+ {
+ newbeg[j] = total;
+ if (A->matcnt[j] > 0)
+ total += A->matcnt[j];
+ else
+ total += 1;
+ }
+ for (i = 0; i < rowcnt; i++)
+ {
+ A->matcnt[rowind[i]]--;
+ }
+ for (j = total; j < A->matsize; j++)
+ {
+ newind[j] = -1;
+ }
+ A->matfree = A->matsize - total;
+
+ for (j = 0; j < ncols; j++)
+ {
+ if (A->matcnt[j] > 0)
+ {
+ stop = A->matbeg[j] + A->matcnt[j];
+ start = newbeg[j];
+ for (k = A->matbeg[j]; k < stop; k++)
+ {
+ newind[start] = A->matind[k];
+ EGLPNUM_TYPENAME_EGlpNumCopy (newval[start], A->matval[k]);
+ start++;
+ }
+ }
+ else
+ {
+ newind[newbeg[j]] = 1;
+ }
+ }
+ for (i = 0; i < rowcnt; i++)
+ {
+ j = rowind[i];
+ newind[newbeg[j] + A->matcnt[j]] = row;
+ EGLPNUM_TYPENAME_EGlpNumCopy (newval[newbeg[j] + A->matcnt[j]], rowval[i]);
+ (A->matcnt[j])++;
+ }
+
+ ILL_IFFREE (A->matbeg, int);
+ ILL_IFFREE (A->matind, int);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (A->matval);
+
+ A->matbeg = newbeg;
+ A->matind = newind;
+ A->matval = newval;
+
+CLEANUP:
+
+ if (rval)
+ {
+ ILL_IFFREE (newbeg, int);
+ ILL_IFFREE (newind, int);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (newval);
+ }
+
+ EG_RETURN (rval);
+}
+
+static int matrix_addcoef (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_ILLmatrix * A,
+ int row,
+ int col,
+ EGLPNUM_TYPE val)
+{
+ int i, k, delta, ind, stop, memo;
+ int tind[1];
+ EGLPNUM_TYPE tval[1];
+ int rval = 0;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (tval[0]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (tval[0], val);
+
+ if (row >= A->matrows || row < 0)
+ {
+ QSlog("illegal row index in matrix_addcoef");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ if (col >= A->matcols || col < 0)
+ {
+ QSlog("illegal col index in matrix_addcoef");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ for (i = A->matbeg[col]; i < A->matbeg[col] + A->matcnt[col]; i++)
+ {
+ if (A->matind[i] == row)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (A->matval[i], val);
+ ILL_CLEANUP;
+ }
+ }
+
+ /* The coef is new, we need to add it to A */
+
+ lp->O->nzcount++;
+ delta = A->matcnt[col] + 2;
+
+ if (A->matcnt[col] == 0)
+ {
+ /* First entry, always a free space */
+ A->matind[A->matbeg[col]] = row;
+ EGLPNUM_TYPENAME_EGlpNumCopy (A->matval[A->matbeg[col]], val);
+ A->matcnt[col] = 1;
+ }
+ else if (A->matbeg[col] + A->matcnt[col] < A->matsize &&
+ A->matind[A->matbeg[col] + A->matcnt[col]] == -1)
+ {
+ /* Free space in the column */
+ A->matind[A->matbeg[col] + A->matcnt[col]] = row;
+ EGLPNUM_TYPENAME_EGlpNumCopy (A->matval[A->matbeg[col] + A->matcnt[col]], val);
+ if ((A->matbeg[col] + A->matcnt[col]) == (A->matsize - A->matfree))
+ {
+ A->matfree--;
+ }
+ (A->matcnt[col])++;
+ }
+ else if (A->matfree > delta)
+ {
+ /* Enough space to move column to end of array */
+ ind = A->matsize - A->matfree + 1;
+ memo = ind;
+ stop = A->matbeg[col] + A->matcnt[col];
+ for (k = A->matbeg[col]; k < stop; k++)
+ {
+ A->matind[ind] = A->matind[k];
+ EGLPNUM_TYPENAME_EGlpNumCopy (A->matval[ind], A->matval[k]);
+ A->matind[k] = -1;
+ ind++;
+ }
+ A->matind[ind] = row;
+ EGLPNUM_TYPENAME_EGlpNumCopy (A->matval[ind], val);
+
+ A->matbeg[col] = memo;
+ (A->matcnt[col])++;
+ (A->matfree) -= (A->matcnt[col] + 1);
+ }
+ else
+ {
+ /* Need to malloc space to move column to end of array */
+
+ tind[0] = col;
+
+ rval = matrix_addrow_end (A, row, 1, tind, tval);
+ CHECKRVALG (rval, CLEANUP);
+ }
+
+CLEANUP:
+
+ EGLPNUM_TYPENAME_EGlpNumClearVar (tval[0]);
+ EG_RETURN (rval);
+}
+
+static int matrix_addcol (
+ EGLPNUM_TYPENAME_ILLmatrix * A,
+ int colcnt,
+ int *colind,
+ EGLPNUM_TYPE * colval)
+{
+ int rval = 0;
+ int i, ind;
+
+ for (i = 0; i < colcnt; i++)
+ {
+ if (colind[i] >= A->matrows || colind[i] < 0)
+ {
+ QSlog("illegal row index in matrix_addcol");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+ }
+
+ if (A->matcolsize < A->matcols + 1)
+ {
+ A->matbeg =
+ EGrealloc (A->matbeg, sizeof (int) * (A->matcolsize + EXTRA_COLS));
+ //rval = ILLutil_reallocrus_count ((void **) &(A->matbeg),
+ // A->matcolsize + EXTRA_COLS, sizeof (int));
+ //CHECKRVALG(rval,CLEANUP);
+
+ A->matcnt =
+ EGrealloc (A->matcnt, sizeof (int) * (A->matcolsize + EXTRA_COLS));
+ //rval = ILLutil_reallocrus_count ((void **) &(A->matcnt),
+ // A->matcolsize + EXTRA_COLS, sizeof (int));
+ //CHECKRVALG(rval,CLEANUP);
+
+ (A->matcolsize) += EXTRA_COLS;
+ }
+
+ if (A->matfree < colcnt + 1)
+ {
+ A->matind = EGrealloc (A->matind,
+ sizeof (int) * (A->matsize + colcnt + EXTRA_MAT +
+ 1));
+ //rval = ILLutil_reallocrus_count ((void **) &(A->matind),
+ // A->matsize + colcnt + EXTRA_MAT + 1,
+ // sizeof (int));
+ //CHECKRVALG(rval,CLEANUP);
+ EGLPNUM_TYPENAME_EGlpNumReallocArray (&(A->matval), A->matsize + colcnt + EXTRA_MAT + 1);
+
+ for (i = 0; i < colcnt + EXTRA_MAT + 1; i++)
+ {
+ A->matind[A->matsize + i] = -1;
+ }
+ A->matsize += (colcnt + EXTRA_MAT + 1);
+ A->matfree += (colcnt + EXTRA_MAT + 1);
+ }
+
+ ind = A->matsize - A->matfree;
+ A->matbeg[A->matcols] = ind;
+ A->matcnt[A->matcols] = colcnt;
+ if (colcnt == 0)
+ {
+ A->matind[ind] = 1; /* Dummy value to stop columns from stealing */
+ /* this space in addrows. */
+ A->matfree -= 1;
+ }
+ else
+ {
+ for (i = 0; i < colcnt; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (A->matval[ind], colval[i]);
+ A->matind[ind] = colind[i];
+ ind++;
+ }
+ A->matfree -= colcnt;
+ }
+ A->matcols++;
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_getrows (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int num,
+ int *rowlist,
+ int **rowcnt,
+ int **rowbeg,
+ int **rowind,
+ EGLPNUM_TYPE ** rowval,
+ EGLPNUM_TYPE ** rhs,
+ char **sense,
+ EGLPNUM_TYPE ** range,
+ char ***names)
+{
+ int rval = 0;
+ int *allbeg = 0;
+ int *allcnt = 0;
+ int *allind = 0;
+ EGLPNUM_TYPE *allval = 0;
+ int i, row, k, start, stop, len, tcnt, cnt = 0;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp;
+ EGLPNUM_TYPENAME_ILLlp_rows lprows;
+
+ if (rowcnt) *rowcnt = 0;
+ if (rowbeg) *rowbeg = 0;
+ if (rowind) *rowind = 0;
+ if (rowval) *rowval = 0;
+ if (rhs) *rhs = 0;
+ if (range) *range = 0;
+ if (sense) *sense = 0;
+ if (names) *names = 0;
+
+ if (!lp)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_getrows called without an LP");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ if (!num)
+ ILL_CLEANUP;
+
+ qslp = lp->O;
+
+ rval = EGLPNUM_TYPENAME_ILLlp_rows_init (&lprows, qslp, 0);
+ CHECKRVALG (rval, CLEANUP);
+ allbeg = lprows.rowbeg;
+ allcnt = lprows.rowcnt;
+ allind = lprows.rowind;
+ allval = lprows.rowval;
+
+ for (i = 0; i < num; i++)
+ {
+ cnt += allcnt[rowlist[i]];
+ }
+
+ if (rowcnt)
+ {
+ ILL_SAFE_MALLOC (*rowcnt, num, int);
+
+ for (i = 0; i < num; i++)
+ {
+ (*rowcnt)[i] = allcnt[rowlist[i]];
+ }
+ }
+
+ if (rowbeg)
+ {
+ ILL_SAFE_MALLOC (*rowbeg, num, int);
+
+ tcnt = 0;
+ for (i = 0; i < num; i++)
+ {
+ (*rowbeg)[i] = tcnt;
+ tcnt += allcnt[rowlist[i]];
+ }
+ }
+
+ if (cnt && rowind)
+ {
+ ILL_SAFE_MALLOC (*rowind, cnt, int);
+
+ tcnt = 0;
+ for (i = 0; i < num; i++)
+ {
+ row = rowlist[i];
+ start = allbeg[row];
+ stop = start + allcnt[row];
+ for (k = start; k < stop; k++)
+ {
+ (*rowind)[tcnt++] = allind[k];
+ }
+ }
+ }
+
+ if (cnt && rowval)
+ {
+ *rowval = EGLPNUM_TYPENAME_EGlpNumAllocArray (cnt);
+ tcnt = 0;
+ for (i = 0; i < num; i++)
+ {
+ row = rowlist[i];
+ start = allbeg[row];
+ stop = start + allcnt[row];
+ for (k = start; k < stop; k++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy ((*rowval)[tcnt++], allval[k]);
+ }
+ }
+ }
+
+ if (rhs)
+ {
+ *rhs = EGLPNUM_TYPENAME_EGlpNumAllocArray (num);
+ for (i = 0; i < num; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy ((*rhs)[i], qslp->rhs[rowlist[i]]);
+ }
+ }
+
+ if (range)
+ {
+ *range = EGLPNUM_TYPENAME_EGlpNumAllocArray(num);
+ if(qslp->rangeval)
+ {
+ for(i = 0; i < num ; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy((*range)[i], qslp->rangeval[rowlist[i]]);
+ }
+ }
+ else
+ {
+ for(i = 0; i < num ; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumZero((*range)[i]);
+ }
+ }
+ }
+
+ if (sense)
+ {
+ ILL_SAFE_MALLOC (*sense, num, char);
+
+ for (i = 0; i < num; i++)
+ {
+ (*sense)[i] = qslp->sense[rowlist[i]];
+ }
+ }
+
+ if (names)
+ {
+ if (qslp->rownames == 0)
+ {
+ QSlog("LP does not have row names");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+ ILL_SAFE_MALLOC (*names, num, char *);
+
+ for (i = 0; i < num; i++)
+ {
+ (*names)[i] = 0;
+ }
+ for (i = 0; i < num; i++)
+ {
+ len = strlen (qslp->rownames[rowlist[i]]) + 1;
+ ILL_SAFE_MALLOC ((*names)[i], len, char);
+
+ strcpy ((*names)[i], qslp->rownames[rowlist[i]]);
+ }
+ }
+
+CLEANUP:
+
+ ILL_IFFREE (allbeg, int);
+ ILL_IFFREE (allcnt, int);
+ ILL_IFFREE (allind, int);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (allval);
+
+ if (rval)
+ {
+ if (rowcnt)
+ ILL_IFFREE (*rowcnt, int);
+
+ if (rowbeg)
+ ILL_IFFREE (*rowbeg, int);
+
+ if (rowind)
+ ILL_IFFREE (*rowind, int);
+
+ if (rowval)
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (*rowval);
+ if (rhs)
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (*rhs);
+ if (sense)
+ ILL_IFFREE (*sense, char);
+
+ if (names && (*names))
+ {
+ for (i = 0; i < num; i++)
+ {
+ ILL_IFFREE ((*names)[i], char);
+ }
+ ILL_IFFREE (*names, char *);
+ }
+ }
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_getcols (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int num,
+ int *collist,
+ int **colcnt,
+ int **colbeg,
+ int **colind,
+ EGLPNUM_TYPE ** colval,
+ EGLPNUM_TYPE ** obj,
+ EGLPNUM_TYPE ** lower,
+ EGLPNUM_TYPE ** upper,
+ char ***names)
+{
+ int rval = 0;
+ int i, col, k, start, stop, len, tcnt, cnt = 0;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp;
+ EGLPNUM_TYPENAME_ILLmatrix *A;
+ int *tlist = 0;
+
+ if (colcnt)
+ *colcnt = 0;
+ if (colbeg)
+ *colbeg = 0;
+ if (colind)
+ *colind = 0;
+ if (colval)
+ *colval = 0;
+ if (lower)
+ *lower = 0;
+ if (upper)
+ *upper = 0;
+ if (obj)
+ *obj = 0;
+ if (names)
+ *names = 0;
+
+ if (!lp)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_getcols called without an LP");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ if (!num)
+ ILL_CLEANUP;
+
+ qslp = lp->O;
+ A = &(qslp->A);
+
+ ILL_SAFE_MALLOC (tlist, num, int);
+
+ for (i = 0; i < num; i++)
+ {
+ tlist[i] = qslp->structmap[collist[i]];
+ }
+
+ for (i = 0; i < num; i++)
+ {
+ cnt += A->matcnt[tlist[i]];
+ }
+
+ if (colcnt)
+ {
+ ILL_SAFE_MALLOC (*colcnt, num, int);
+
+ for (i = 0; i < num; i++)
+ {
+ (*colcnt)[i] = A->matcnt[tlist[i]];
+ }
+ }
+
+ if (colbeg)
+ {
+ ILL_SAFE_MALLOC (*colbeg, num, int);
+
+ tcnt = 0;
+ for (i = 0; i < num; i++)
+ {
+ (*colbeg)[i] = tcnt;
+ tcnt += A->matcnt[tlist[i]];
+ }
+ }
+
+ if (cnt && colind)
+ {
+ ILL_SAFE_MALLOC (*colind, cnt, int);
+
+ tcnt = 0;
+ for (i = 0; i < num; i++)
+ {
+ col = tlist[i];
+ start = A->matbeg[col];
+ stop = start + A->matcnt[col];
+ for (k = start; k < stop; k++)
+ {
+ (*colind)[tcnt++] = A->matind[k];
+ }
+ }
+ }
+
+ if (cnt && colval)
+ {
+ *colval = EGLPNUM_TYPENAME_EGlpNumAllocArray (cnt);
+ tcnt = 0;
+ for (i = 0; i < num; i++)
+ {
+ col = tlist[i];
+ start = A->matbeg[col];
+ stop = start + A->matcnt[col];
+ for (k = start; k < stop; k++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy ((*colval)[tcnt++], A->matval[k]);
+ }
+ }
+ }
+
+ if (obj)
+ {
+ *obj = EGLPNUM_TYPENAME_EGlpNumAllocArray (num);
+ for (i = 0; i < num; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy ((*obj)[i], qslp->obj[tlist[i]]);
+ }
+ }
+
+ if (lower)
+ {
+ *lower = EGLPNUM_TYPENAME_EGlpNumAllocArray (num);
+ for (i = 0; i < num; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy ((*lower)[i], qslp->lower[tlist[i]]);
+ }
+ }
+
+ if (upper)
+ {
+ *upper = EGLPNUM_TYPENAME_EGlpNumAllocArray (num);
+ for (i = 0; i < num; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy ((*upper)[i], qslp->upper[tlist[i]]);
+ }
+ }
+
+ if (names)
+ {
+ if (qslp->colnames == 0)
+ {
+ QSlog("LP does not have col names");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+ ILL_SAFE_MALLOC (*names, num, char *);
+
+ for (i = 0; i < num; i++)
+ {
+ (*names)[i] = 0;
+ }
+ for (i = 0; i < num; i++)
+ {
+ len = strlen (qslp->colnames[collist[i]]) + 1;
+ ILL_SAFE_MALLOC ((*names)[i], len, char);
+
+ strcpy ((*names)[i], qslp->colnames[collist[i]]);
+ }
+ }
+
+CLEANUP:
+
+ if (rval)
+ {
+ if (colcnt)
+ ILL_IFFREE (*colcnt, int);
+
+ if (colbeg)
+ ILL_IFFREE (*colbeg, int);
+
+ if (colind)
+ ILL_IFFREE (*colind, int);
+
+ if (colval)
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (*colval);
+ if (obj)
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (*obj);
+ if (lower)
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (*lower);
+ if (upper)
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (*upper);
+ if (names && (*names))
+ {
+ for (i = 0; i < num; i++)
+ {
+ ILL_IFFREE ((*names)[i], char);
+ }
+ ILL_IFFREE (*names, char *);
+ }
+ }
+ ILL_IFFREE (tlist, int);
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_getobj_list (
+ EGLPNUM_TYPENAME_lpinfo *lp,
+ int num,
+ int* collist,
+ EGLPNUM_TYPE* obj)
+{
+ const int*const structmap = lp->O->structmap;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp;
+ int nstruct, j, col;
+ int rval = 0;
+
+ if (!lp)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_getobj_list called without an LP");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ qslp = lp->O;
+ nstruct = qslp->nstruct;
+
+ for (j = 0; j < num; j++)
+ {
+ col = collist[j];
+ if(col<0 || col >= nstruct)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_getobj_list collist[%d] = %d outside"
+ " valid range", j, col);
+ rval = 1;
+ ILL_CLEANUP;
+ }
+ EGLPNUM_TYPENAME_EGlpNumCopy(obj[j],qslp->obj[structmap[col]]);
+ }
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+
+int EGLPNUM_TYPENAME_ILLlib_getobj (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPE * obj)
+{
+ const int*const structmap = lp->O->structmap;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp;
+ int nstruct, j;
+ int rval = 0;
+
+ if (!lp)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_getobj called without an LP");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ qslp = lp->O;
+ nstruct = qslp->nstruct;
+
+ for (j = 0; j < nstruct; j++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (obj[j], qslp->obj[structmap[j]]);
+ }
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_chgobj (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int indx,
+ EGLPNUM_TYPE coef)
+{
+ int rval = 0;
+ int col;
+
+ if (!lp)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_chgobj called without an lp");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ if (indx < 0 || indx >= lp->O->nstruct)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_chgrhs called with bad indx: %d", indx);
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ if (lp->O->sinfo)
+ { /* Presolve LP is no longer valid, free the data */
+ EGLPNUM_TYPENAME_ILLlp_sinfo_free (lp->O->sinfo);
+ ILL_IFFREE (lp->O->sinfo, EGLPNUM_TYPENAME_ILLlp_sinfo);
+ }
+
+ col = lp->O->structmap[indx];
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->O->obj[col], coef);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_getrhs (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPE * rhs)
+{
+ EGLPNUM_TYPENAME_ILLlpdata *qslp;
+ int nrows, i;
+ int rval = 0;
+
+ if (!lp)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_getrhs called without an LP");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ qslp = lp->O;
+ nrows = qslp->nrows;
+
+ for (i = 0; i < nrows; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (rhs[i], qslp->rhs[i]);
+ }
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_chgrange (
+ EGLPNUM_TYPENAME_lpinfo *lp,
+ int indx,
+ EGLPNUM_TYPE coef)
+{
+ register int i;
+ int rval = 0;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp;
+
+ if (!lp)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_chgrhs called without an lp");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ if (indx < 0 || indx >= lp->O->nrows)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_chgrhs called with bad indx: %d", indx);
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ if (lp->O->sinfo)
+ {/* Presolve LP is no longer valid, free the data */
+ EGLPNUM_TYPENAME_ILLlp_sinfo_free (lp->O->sinfo);
+ ILL_IFFREE (lp->O->sinfo, EGLPNUM_TYPENAME_ILLlp_sinfo);
+ }
+
+ qslp = lp->O;
+ if(qslp->rangeval == 0)
+ {
+ qslp->rangeval = EGLPNUM_TYPENAME_EGlpNumAllocArray(qslp->rowsize);
+ for( i = qslp->nrows ; i-- ; )
+ {
+ EGLPNUM_TYPENAME_EGlpNumZero(qslp->rangeval[i]);
+ }
+ }
+
+ if(qslp->sense[indx] != 'R')
+ {
+ QSlog("setting range for non-range constraint");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ EGLPNUM_TYPENAME_EGlpNumCopy(qslp->rangeval[indx], coef);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+
+int EGLPNUM_TYPENAME_ILLlib_chgrhs (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int indx,
+ EGLPNUM_TYPE coef)
+{
+ int rval = 0;
+
+ if (!lp)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_chgrhs called without an lp");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ if (indx < 0 || indx >= lp->O->nrows)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_chgrhs called with bad indx: %d", indx);
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ if (lp->O->sinfo)
+ { /* Presolve LP is no longer valid, free the data */
+ EGLPNUM_TYPENAME_ILLlp_sinfo_free (lp->O->sinfo);
+ ILL_IFFREE (lp->O->sinfo, EGLPNUM_TYPENAME_ILLlp_sinfo);
+ }
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->O->rhs[indx], coef);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_rownames (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ char **rownames)
+{
+ EGLPNUM_TYPENAME_ILLlpdata *qslp;
+ int nrows, len, i, rcount = 0;
+ int rval = 0;
+
+ if (!lp)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_rownames called without an LP");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+ if (!rownames)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_rownames called with NULL rownames");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ qslp = lp->O;
+ nrows = qslp->nrows;
+
+ if (qslp->rownames == 0)
+ {
+ QSlog("LP does not have rownames assigned");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ for (i = 0; i < nrows; i++)
+ {
+ len = strlen (qslp->rownames[i]) + 1;
+ ILL_SAFE_MALLOC (rownames[i], len, char);
+
+ strcpy (rownames[i], qslp->rownames[i]);
+ rcount++;
+ }
+
+CLEANUP:
+
+ if (rval)
+ {
+ for (i = 0; i < rcount; i++)
+ {
+ ILL_IFFREE (rownames[i], char);
+ }
+ }
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_getintflags (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int *intflags)
+{
+ int j, nstruct, rval = 0;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp;
+
+ if (!lp)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_getintflags called without an LP");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ qslp = lp->O;
+ nstruct = qslp->nstruct;
+
+ if (qslp->intmarker == 0)
+ {
+ for (j = 0; j < nstruct; j++)
+ {
+ intflags[j] = 0;
+ }
+ }
+ else
+ {
+ for (j = 0; j < nstruct; j++)
+ {
+ if (qslp->intmarker[j])
+ {
+ intflags[j] = 1;
+ }
+ else
+ {
+ intflags[j] = 0;
+ }
+ }
+ }
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_colnames (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ char **colnames)
+{
+ EGLPNUM_TYPENAME_ILLlpdata *qslp;
+ int nstruct, len, i, ccount = 0;
+ int rval = 0;
+
+ if (!lp)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_colnames called without an LP");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+ if (!colnames)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_colnames called with NULL colnames");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ qslp = lp->O;
+ nstruct = qslp->nstruct;
+
+ if (qslp->colnames == 0)
+ {
+ QSlog("LP does not have colnames assigned");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ for (i = 0; i < nstruct; i++)
+ {
+ len = strlen (qslp->colnames[i]) + 1;
+ ILL_SAFE_MALLOC (colnames[i], len, char);
+
+ strcpy (colnames[i], qslp->colnames[i]);
+ ccount++;
+ }
+
+
+CLEANUP:
+
+ if (rval)
+ {
+ for (i = 0; i < ccount; i++)
+ {
+ ILL_IFFREE (colnames[i], char);
+ }
+ }
+
+ EG_RETURN (rval);
+}
+
+static int reset_colindex (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ int rval = 0;
+ int test;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp = lp->O;
+
+ test = ILLsymboltab_index_ok (&qslp->coltab);
+ if (!test)
+ {
+ rval = ILLsymboltab_index_reset (&qslp->coltab, qslp->nstruct,
+ qslp->colnames);
+ CHECKRVALG (rval, CLEANUP);
+ }
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+static int reset_rowindex (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ int rval = 0;
+ int test;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp = lp->O;
+
+ test = ILLsymboltab_index_ok (&qslp->rowtab);
+ if (!test)
+ {
+ rval = ILLsymboltab_index_reset (&qslp->rowtab, qslp->nrows,
+ qslp->rownames);
+ CHECKRVALG (rval, CLEANUP);
+ }
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_colindex (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ const char *name,
+ int *colindex)
+{
+ int rval = 0;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp;
+
+ *colindex = -1;
+
+ if (!lp)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_colindex called without an LP");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ qslp = lp->O;
+
+ rval = reset_colindex (lp);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = ILLsymboltab_getindex (&qslp->coltab, name, colindex);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_rowindex (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ const char *name,
+ int *rowindex)
+{
+ int rval = 0;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp;
+
+ *rowindex = -1;
+
+ if (!lp)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_rowindex called without an LP");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ qslp = lp->O;
+
+ rval = reset_rowindex (lp);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = ILLsymboltab_getindex (&qslp->rowtab, name, rowindex);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_getbasis (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ char *cstat,
+ char *rstat)
+{
+ int rval = 0;
+ int i, j, nrows;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp;
+
+ if (!lp)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_getbasis called without an LP");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ if (lp->basisid == -1)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_getbasis called with modifed LP");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ nrows = lp->O->nrows;
+ qslp = lp->O;
+
+ for (i = 0; i < qslp->nstruct; i++)
+ {
+ j = qslp->structmap[i];
+ switch (lp->vstat[j])
+ {
+ case STAT_BASIC:
+ cstat[i] = QS_COL_BSTAT_BASIC;
+ break;
+ case STAT_LOWER:
+ cstat[i] = QS_COL_BSTAT_LOWER;
+ break;
+ case STAT_UPPER:
+ cstat[i] = QS_COL_BSTAT_UPPER;
+ break;
+ case STAT_ZERO:
+ cstat[i] = QS_COL_BSTAT_FREE;
+ break;
+ default:
+ QSlog("unknown vstat in EGLPNUM_TYPENAME_ILLlib_getbasis: %d", lp->vstat[j]);
+ rval = 1;
+ ILL_CLEANUP;
+ }
+ }
+
+ for (i = 0; i < nrows; i++)
+ {
+ j = qslp->rowmap[i];
+ if (qslp->rangeval && EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (qslp->rangeval[i]))
+ {
+ switch (lp->vstat[j])
+ {
+ case STAT_BASIC:
+ rstat[i] = QS_ROW_BSTAT_BASIC;
+ break;
+ case STAT_LOWER:
+ rstat[i] = QS_ROW_BSTAT_LOWER;
+ break;
+ case STAT_UPPER:
+ rstat[i] = QS_ROW_BSTAT_UPPER;
+ break;
+ default:
+ QSlog("unknown vstat in EGLPNUM_TYPENAME_ILLlib_getbasis 2");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+ }
+ else
+ {
+ switch (lp->vstat[j])
+ {
+ case STAT_BASIC:
+ rstat[i] = QS_ROW_BSTAT_BASIC;
+ break;
+ case STAT_UPPER:
+ case STAT_LOWER:
+ rstat[i] = QS_ROW_BSTAT_LOWER;
+ break;
+ default:
+ QSlog("unknown vstat in EGLPNUM_TYPENAME_ILLlib_getbasis 3: %d, %d",
+ i, lp->vstat[j]);
+ rval = 1;
+ ILL_CLEANUP;
+ }
+ }
+ }
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_loadbasis (
+ EGLPNUM_TYPENAME_ILLlp_basis * B,
+ int nstruct,
+ int nrows,
+ char *cstat,
+ char *rstat)
+{
+ int i;
+ int rval = 0;
+
+ EGLPNUM_TYPENAME_ILLlp_basis_init (B);
+
+ if (!cstat || !rstat)
+ {
+ rval = 1;
+ CHECKRVALG (rval, CLEANUP);
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLlp_basis_alloc (B, nstruct, nrows);
+ CHECKRVALG (rval, CLEANUP);
+
+ for (i = 0; i < nstruct; i++)
+ {
+ B->cstat[i] = cstat[i];
+ }
+ for (i = 0; i < nrows; i++)
+ {
+ B->rstat[i] = rstat[i];
+ }
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+#define READ_BASIS_XL 0
+#define READ_BASIS_XU 1
+#define READ_BASIS_LL 2
+#define READ_BASIS_UL 3
+
+int EGLPNUM_TYPENAME_ILLlib_readbasis (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_ILLlp_basis * B,
+ const char *fname)
+{
+ int rval = 0;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp = lp->O;
+ int nstruct = qslp->nstruct;
+ int nrows = qslp->nrows;
+ int i, j, end = 0, sec, havename = 0;
+ int rowtype, row, col;
+ char *bname = 0;
+ EGioFile_t *file_in = 0;
+ EGLPNUM_TYPENAME_ILLread_mps_state state;
+ EGLPNUM_TYPENAME_qsline_reader *in = NULL;
+
+ EGLPNUM_TYPENAME_ILLlp_basis_init (B);
+
+ ILL_SAFE_MALLOC (B->cstat, qslp->nstruct, char);
+ ILL_SAFE_MALLOC (B->rstat, qslp->nrows, char);
+
+ B->nstruct = nstruct;
+ B->nrows = nrows;
+
+ for (j = 0; j < nstruct; j++)
+ {
+ B->cstat[j] = QS_COL_BSTAT_LOWER;
+ }
+ for (i = 0; i < nrows; i++)
+ {
+ B->rstat[i] = QS_ROW_BSTAT_BASIC;
+ }
+
+ file_in = EGioOpen (fname, "r");
+ if (file_in == 0)
+ {
+ QSlog("unable to open %s for reading", fname);
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ in = EGLPNUM_TYPENAME_ILLline_reader_new ((EGLPNUM_TYPENAME_qsread_line_fct) EGioGets, file_in);
+ rval = EGLPNUM_TYPENAME_ILLmps_state_init (&state, in, fname);
+ CHECKRVALG (rval, CLEANUP);
+
+ while (EGLPNUM_TYPENAME_ILLmps_next_line (&state) == 0)
+ {
+ if (EGLPNUM_TYPENAME_ILLmps_empty_key (&state))
+ {
+
+ /* Get the XL XU LL UL line */
+
+ if (!havename)
+ {
+ rval = EGLPNUM_TYPENAME_ILLmps_error (&state, "BASIS data before NAME\n");
+ ILL_CLEANUP;
+ }
+
+ if (!strcmp (state.field, "XL"))
+ {
+ rowtype = READ_BASIS_XL;
+ }
+ else if (!strcmp (state.field, "XU"))
+ {
+ rowtype = READ_BASIS_XU;
+ }
+ else if (!strcmp (state.field, "LL"))
+ {
+ rowtype = READ_BASIS_LL;
+ }
+ else if (!strcmp (state.field, "UL"))
+ {
+ rowtype = READ_BASIS_UL;
+ }
+ else
+ {
+ rval = EGLPNUM_TYPENAME_ILLmps_error (&state, "BASIS \"%s\" is invalid\n", state.field);
+ ILL_CLEANUP;
+ }
+
+ if (EGLPNUM_TYPENAME_ILLmps_next_field (&state) == 0)
+ {
+
+ rval = EGLPNUM_TYPENAME_ILLlib_colindex (lp, (const char *) state.field, &col);
+ CHECKRVALG (rval, CLEANUP);
+ if (col == -1)
+ {
+ rval = EGLPNUM_TYPENAME_ILLmps_error (&state, "BASIS col not in LP\n");
+ ILL_CLEANUP;
+ }
+
+ if (rowtype == READ_BASIS_XL || rowtype == READ_BASIS_XU)
+ {
+ if (EGLPNUM_TYPENAME_ILLmps_next_field (&state) == 0)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlib_rowindex (lp, (const char *) state.field, &row);
+ CHECKRVALG (rval, CLEANUP);
+ if (row == -1)
+ {
+ rval = EGLPNUM_TYPENAME_ILLmps_error (&state, "BASIS row not in LP\n");
+ ILL_CLEANUP;
+ }
+ if (rowtype == READ_BASIS_XL)
+ {
+ B->cstat[col] = QS_COL_BSTAT_BASIC;
+ B->rstat[row] = QS_ROW_BSTAT_LOWER;
+
+ }
+ else
+ {
+ B->cstat[col] = QS_COL_BSTAT_BASIC;
+ B->rstat[row] = QS_ROW_BSTAT_UPPER;
+ }
+ }
+ else
+ {
+ rval = EGLPNUM_TYPENAME_ILLmps_error (&state, "BASIS line needs row and column\n");
+ ILL_CLEANUP;
+ }
+ }
+ else
+ {
+ if (rowtype == READ_BASIS_LL)
+ {
+ B->cstat[col] = QS_COL_BSTAT_LOWER;
+ }
+ else
+ {
+ B->cstat[col] = QS_COL_BSTAT_UPPER;
+ }
+ }
+ }
+ else
+ {
+ rval = EGLPNUM_TYPENAME_ILLmps_error (&state, "BASIS line has no row/column\n");
+ ILL_CLEANUP;
+ }
+ }
+ else
+ {
+ /* found a section indicator in col 1 */
+ if (!strcmp (state.key, EGLPNUM_TYPENAME_ILLmps_section_name[ILL_MPS_ENDATA]))
+ {
+ end = 1;
+ break; /* done reading */
+ }
+
+ sec = ILLutil_index (EGLPNUM_TYPENAME_ILLmps_section_name, state.key);
+ if (sec < 0 || sec != ILL_MPS_NAME)
+ {
+ rval = EGLPNUM_TYPENAME_ILLmps_error (&state, "BASIS \"%s\" is not a key\n", state.key);
+ ILL_CLEANUP;
+ }
+
+ if (havename)
+ {
+ rval = EGLPNUM_TYPENAME_ILLmps_error (&state, "BASIS two name sections\n");
+ ILL_CLEANUP;
+ }
+
+ havename = 1;
+
+ if (EGLPNUM_TYPENAME_ILLmps_empty_field (&state))
+ {
+ EGLPNUM_TYPENAME_ILLmps_warn (&state, "BASIS blank NAME.");
+ }
+ else
+ {
+ ILL_UTIL_STR (bname, state.field);
+ QSlog("Basis Name: %s", bname);
+ if (strcmp (bname, qslp->probname))
+ {
+ EGLPNUM_TYPENAME_ILLmps_warn (&state, "BASIS name does not match LP.");
+ }
+ }
+ }
+ }
+
+ if (!end)
+ {
+ EGLPNUM_TYPENAME_ILLmps_warn (&state, "Missing ENDATA in basis file.");
+ }
+ if (!EGLPNUM_TYPENAME_ILLmps_next_line (&state))
+ {
+ EGLPNUM_TYPENAME_ILLmps_warn (&state, "Ignoring text after ENDATA.");
+ }
+
+ if (!havename)
+ {
+ rval = EGLPNUM_TYPENAME_ILLmps_error (&state, "BASIS no name section\n");
+ ILL_CLEANUP;
+ }
+
+ /* Correct the free variables */
+
+ for (j = 0; j < nstruct; j++)
+ {
+ col = lp->O->structmap[j];
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (qslp->lower[col], EGLPNUM_TYPENAME_ILL_MINDOUBLE) &&
+ EGLPNUM_TYPENAME_EGlpNumIsEqqual (qslp->upper[col], EGLPNUM_TYPENAME_ILL_MAXDOUBLE) &&
+ B->cstat[j] == QS_COL_BSTAT_LOWER)
+ {
+ B->cstat[j] = QS_COL_BSTAT_FREE;
+ }
+ }
+
+CLEANUP:
+
+ if (file_in)
+ EGioClose (file_in);
+ EGLPNUM_TYPENAME_ILLline_reader_free (in);
+
+ if (rval)
+ {
+ EGLPNUM_TYPENAME_ILLlp_basis_free (B);
+ }
+ ILL_IFFREE (bname, char);
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_writebasis (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_ILLlp_basis * B,
+ const char *fname)
+{
+ int rval = 0;
+ EGioFile_t *out = 0;
+ char *cstat = 0;
+ char *rstat = 0;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp;
+ int i, j, nstruct, nrows;
+
+ /* NOTE: non-basic free variables are encoded as non-basic at lower */
+
+ if (!lp)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_writebasis called without an LP");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+ if (!B && lp->basisid == -1)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlib_writebasis called with unsolved LP");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ qslp = lp->O;
+ nstruct = qslp->nstruct;
+ nrows = qslp->nrows;
+
+ out = EGioOpen (fname, "w");
+ if (out == 0)
+ {
+ QSlog("unable to open %s for writing", fname);
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ if (B)
+ {
+ cstat = B->cstat;
+ rstat = B->rstat;
+ }
+ else
+ {
+ ILL_SAFE_MALLOC (cstat, nstruct, char);
+ ILL_SAFE_MALLOC (rstat, nrows, char);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_getbasis (lp, cstat, rstat);
+ CHECKRVALG (rval, CLEANUP);
+ }
+
+ EGioPrintf (out, "NAME %s\n", qslp->probname);
+
+ /* Pick out the non-basic rows and find a matching basic column */
+
+ i = 0;
+ j = 0;
+ do
+ {
+ while (i < nrows && rstat[i] == QS_ROW_BSTAT_BASIC)
+ {
+ i++;
+ }
+ if (i < nrows)
+ {
+ while (j < nstruct && cstat[j] != QS_COL_BSTAT_BASIC)
+ {
+ j++;
+ }
+ if (j == nstruct)
+ {
+ /* No basic column to match the non-basic row */
+ QSlog("No basic column to match non-basic row %d", i);
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ if (rstat[i] == QS_ROW_BSTAT_LOWER)
+ {
+ EGioPrintf (out, " XL %s %s\n", qslp->colnames[j], qslp->rownames[i]);
+ }
+ else
+ {
+ EGioPrintf (out, " XU %s %s\n", qslp->colnames[j], qslp->rownames[i]);
+ }
+ i++;
+ j++;
+ }
+ } while (i < nrows);
+
+ /* Now go through and output the non-basic cols at upper bound */
+
+ for (j = 0; j < nstruct; j++)
+ {
+ if (cstat[j] == QS_COL_BSTAT_UPPER)
+ {
+ EGioPrintf (out, " UL %s\n", qslp->colnames[j]);
+ }
+ }
+
+ EGioPrintf (out, "ENDATA\n");
+
+CLEANUP:
+
+ if (out)
+ EGioClose (out);
+ if (!B)
+ {
+ ILL_IFFREE (cstat, char);
+ ILL_IFFREE (rstat, char);
+ }
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_getrownorms (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * pinf,
+ EGLPNUM_TYPE * rownorms)
+{
+ int rval = 0;
+ int i, j, basic = 0;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp = lp->O;
+ int nstruct = lp->O->nstruct;
+ int nrows = lp->O->nrows;
+
+ check_pinf (pinf, &rval);
+ if (rval)
+ {
+/*
+ QSlog("dual steepest edge norms not available");
+*/
+ ILL_CLEANUP;
+ }
+
+ for (i = 0; i < nstruct; i++)
+ {
+ j = qslp->structmap[i];
+ if (lp->vstat[j] == STAT_BASIC)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (rownorms[basic++], pinf->dsinfo.norms[lp->vindex[j]]);
+ }
+ }
+ for (i = 0; i < nrows; i++)
+ {
+ j = qslp->rowmap[i];
+ if (lp->vstat[j] == STAT_BASIC)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (rownorms[basic++], pinf->dsinfo.norms[lp->vindex[j]]);
+ }
+ }
+
+ if (basic != nrows)
+ {
+ QSlog("error in EGLPNUM_TYPENAME_ILLlib_getrownorms");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+CLEANUP:
+
+/*
+ EG_RETURN(rval);
+*/
+ return rval; /* Don't want error message */
+}
+
+int EGLPNUM_TYPENAME_ILLlib_loadrownorms (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * pinf,
+ EGLPNUM_TYPE * rownorms)
+{
+ int rval = 0;
+
+ rval = EGLPNUM_TYPENAME_ILLprice_load_rownorms (lp, rownorms, pinf);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_recompute_rownorms (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * pinf)
+{
+ int rval = 0;
+
+ rval = EGLPNUM_TYPENAME_ILLprice_build_pricing_info (lp, pinf, DUAL_PHASEII);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_iter (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ int iter = 0;
+
+ if (lp && lp->cnts)
+ {
+ iter = lp->cnts->pI_iter + lp->cnts->pII_iter +
+ lp->cnts->dI_iter + lp->cnts->dII_iter;
+ }
+
+ return iter;
+}
+
+//#define PRINT_TOL 0.000001
+#define PRINT_TOL EGLPNUM_TYPENAME_PFEAS_TOLER
+
+int EGLPNUM_TYPENAME_ILLlib_print_x (
+ EGioFile_t * fd,
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_ILLlp_cache * C,
+ EGLPNUM_TYPE * x,
+ int nonZerosOnly)
+{
+ int rval = 0;
+ int j;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp = lp->O;
+ EGLPNUM_TYPE *dx, *myx = 0;
+ char *strtmp;
+
+ /* If x is not specified, grab the LP solution */
+
+ if (!x)
+ {
+ myx = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->ncols);
+ rval = EGLPNUM_TYPENAME_ILLlib_get_x (lp, C, myx);
+ CHECKRVALG (rval, CLEANUP);
+ dx = myx;
+ }
+ else
+ {
+ dx = x;
+ }
+
+ EGioPrintf (fd, "Solution Values\n");
+ for (j = 0; j < qslp->nstruct; j++)
+ {
+ /*if (!nonZerosOnly || dx[j] > PRINT_TOL || dx[j] < -PRINT_TOL) */
+ if (!nonZerosOnly || EGLPNUM_TYPENAME_EGlpNumIsNeqZero (dx[j], PRINT_TOL))
+ {
+ strtmp = EGLPNUM_TYPENAME_EGlpNumGetStr (dx[j]);
+ ILL_FAILfalse (qslp->colnames[j] != NULL, "no NULL names PLEASE!");
+ EGioPrintf (fd, "%s = %s\n", qslp->colnames[j], strtmp);
+ EGioFlush (fd);
+ EGfree (strtmp);
+ }
+ }
+
+CLEANUP:
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (myx);
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLlib_findName (
+ EGLPNUM_TYPENAME_ILLlpdata * qslp,
+ int forRow,
+ const char *name,
+ int id,
+ char buf[ILL_namebufsize])
+{
+ ILLsymboltab *tab;
+ const char *mode;
+ const char *p1, *p2;
+ int sind, rval = 0;
+
+ id++;
+ tab = (forRow) ? &qslp->rowtab : &qslp->coltab;
+ if (tab->tablesize == 0)
+ ILLsymboltab_create (tab, 100);
+ p1 = (forRow) ? "c" : "x";
+ p2 = (forRow) ? "c_" : "x_";
+ mode = (forRow) ? "row" : "column";
+ if (name == 0)
+ {
+ ILLsymboltab_unique_name (tab, id, p1, buf);
+ /*
+ * QSlog("Generating %s name \"%s\".", mode, buf);
+ */
+ }
+ else
+ {
+ strcpy (buf, name);
+ }
+ if (!ILLsymboltab_lookup (tab, buf, &sind))
+ {
+ rval = ILLsymboltab_uname (&qslp->rowtab, buf, p1, p2);
+ if (name != NULL)
+ {
+ QSlog("Changing %s name \"%s\" to \"%s\".", mode, name, buf);
+ }
+ CHECKRVALG (rval, CLEANUP);
+ }
+CLEANUP:
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLwrite_lp_file (
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ EGioFile_t * out,
+ EGLPNUM_TYPENAME_qserror_collector * c)
+{
+ int rval = 0;
+ qsstring_reporter rep;
+
+ ILLstring_reporter_copy (&rep, &lp->reporter);
+ ILLstring_reporter_init (&lp->reporter, (qsreport_string_fct) EGioWrite, out);
+ rval = EGLPNUM_TYPENAME_ILLwrite_lp (lp, c);
+ ILLstring_reporter_copy (&lp->reporter, &rep);
+ return rval;
+}
+
+static void check_pinf (
+ EGLPNUM_TYPENAME_price_info * pinf,
+ int *it_exists)
+{
+ if (!pinf || pinf->dI_price != QS_PRICE_DSTEEP ||
+ pinf->dII_price != QS_PRICE_DSTEEP || pinf->dsinfo.norms == 0)
+ {
+ *it_exists = 1;
+ }
+ else
+ {
+ *it_exists = 0;
+ }
+}
+
+#if 0
+static int test_matrix (
+ EGLPNUM_TYPENAME_ILLmatrix * A)
+{
+ int rval = 0;
+ int i, j, k;
+ int ncols = A->matcols;
+ int nrows = A->matrows;
+ int matsize = A->matsize;
+ int *mbeg = A->matbeg;
+ int *mcnt = A->matcnt;
+ int *mind = A->matind;
+ int *tempi = 0;
+
+
+ if (matsize == 0)
+ ILL_CLEANUP;
+
+ ILL_SAFE_MALLOC (tempi, matsize, int);
+
+ for (i = 0; i < matsize; i++)
+ tempi[i] = 0;
+
+ for (i = 0; i < ncols; i++)
+ {
+ for (j = 0; j < mcnt[i]; j++)
+ {
+ k = mind[mbeg[i] + j];
+ if (k < 0 || k >= nrows)
+ {
+ QSlog("ERROR IN MATRIX: %d", k);
+ QSlog("ncols = %d, bad col = %d", ncols, i);
+ QSlog("bad cnt = %d, bad index = %d", mcnt[i], mbeg[i] + j);
+ QSlog("matcolsize = %d, matsize = %d", A->matcolsize, A->matsize);
+ rval = 1;
+ ILL_CLEANUP;
+ }
+ if (tempi[mbeg[i] + j] != 0)
+ {
+ QSlog("ERROR: over written matrix");
+ QSlog("ncols = %d, bad col = %d", ncols, i);
+ QSlog("nrows = %d", nrows);
+ QSlog("bad cnt = %d, bad index = %d", mcnt[i], mbeg[i] + j);
+ rval = 1;
+ ILL_CLEANUP;
+ }
+ else
+ {
+ tempi[mbeg[i] + j] = 1;
+ }
+ }
+ }
+
+ for (i = A->matsize - A->matfree; i < A->matsize; i++)
+ {
+ if (tempi[i] != 0)
+ {
+ QSlog("ERROR: free space is being used");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+ }
+
+CLEANUP:
+
+ ILL_IFFREE (tempi, int);
+
+ EG_RETURN (rval);
+}
+#endif
diff --git a/qsopt_ex/lib.h b/qsopt_ex/lib.h
new file mode 100644
index 0000000..8ee8982
--- /dev/null
+++ b/qsopt_ex/lib.h
@@ -0,0 +1,150 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCSINFO $Id: lib_EGLPNUM_TYPENAME.h,v 1.4 2003/11/05 17:00:26 meven Exp $ */
+#ifndef EGLPNUM_TYPENAME_ILL_LIB_H
+#define EGLPNUM_TYPENAME_ILL_LIB_H
+
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+#include "lpdata_EGLPNUM_TYPENAME.h"
+#include "price_EGLPNUM_TYPENAME.h"
+#include "basicdefs.h"
+
+/****************************************************************************/
+/* */
+/* Return Status for EGLPNUM_TYPENAME_ILLlib_optimize */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* lib.c */
+/* */
+/****************************************************************************/
+
+struct itcnt_t;
+
+int EGLPNUM_TYPENAME_ILLlib_optimize ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_basis * B, EGLPNUM_TYPENAME_price_info * pinf, int algo,
+ int *status, int simplex_display, struct itcnt_t*itcnt),
+ EGLPNUM_TYPENAME_ILLlib_cache_solution ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_cache * C),
+ EGLPNUM_TYPENAME_ILLlib_solution ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_cache * C, EGLPNUM_TYPE * val,
+ EGLPNUM_TYPE * x, EGLPNUM_TYPE * pi, EGLPNUM_TYPE * slack, EGLPNUM_TYPE * rc),
+ EGLPNUM_TYPENAME_ILLlib_get_x ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_cache * C, EGLPNUM_TYPE * x),
+ EGLPNUM_TYPENAME_ILLlib_get_slack ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_cache * C, EGLPNUM_TYPE * slack),
+ EGLPNUM_TYPENAME_ILLlib_objval ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_cache * C, EGLPNUM_TYPE * val),
+ EGLPNUM_TYPENAME_ILLlib_tableau ( EGLPNUM_TYPENAME_lpinfo * lp, int row, EGLPNUM_TYPE * binv, EGLPNUM_TYPE * tabrow),
+ EGLPNUM_TYPENAME_ILLlib_basis_order ( EGLPNUM_TYPENAME_lpinfo * lp, int *header),
+ EGLPNUM_TYPENAME_ILLlib_newrow ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_basis * B,const EGLPNUM_TYPE rhs, int sense,
+ const EGLPNUM_TYPE range, const char *name),
+ EGLPNUM_TYPENAME_ILLlib_newrows ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_basis * B, int num,const EGLPNUM_TYPE * rhs,
+ char *sense, const EGLPNUM_TYPE * range, const char **names),
+ EGLPNUM_TYPENAME_ILLlib_addrow ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_basis * B, int cnt, int *ind,
+ const EGLPNUM_TYPE * val, const EGLPNUM_TYPE rhs, int sense,const EGLPNUM_TYPE range,
+ const char *rowname),
+ EGLPNUM_TYPENAME_ILLlib_addrows ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_basis * B, int num, int *rmatcnt,
+ int *rmatbeg, int *rmatind,const EGLPNUM_TYPE * rmatval,const EGLPNUM_TYPE * rhs,
+ char *sense, const EGLPNUM_TYPE * range, const char **names, int *nofactor),
+ EGLPNUM_TYPENAME_ILLlib_delrows ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_basis * B, EGLPNUM_TYPENAME_ILLlp_cache * C, int num,
+ int *dellist, int *basis_ok, int *cache_ok),
+ EGLPNUM_TYPENAME_ILLlib_newcol ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_basis * B,const EGLPNUM_TYPE obj,
+ const EGLPNUM_TYPE lower,const EGLPNUM_TYPE upper, const char *name, int factorok),
+ EGLPNUM_TYPENAME_ILLlib_newcols ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_basis * B, int num, EGLPNUM_TYPE * obj,
+ EGLPNUM_TYPE * lower, EGLPNUM_TYPE * upper, const char **names, int factorok),
+ EGLPNUM_TYPENAME_ILLlib_addcol ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_basis * B, int cnt, int *ind,
+ EGLPNUM_TYPE * val,const EGLPNUM_TYPE obj,const EGLPNUM_TYPE lower,const EGLPNUM_TYPE upper,
+ const char *name, int factorok),
+ EGLPNUM_TYPENAME_ILLlib_addcols ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_basis * B, int num, int *cmatcnt,
+ int *cmatbeg, int *cmatind, EGLPNUM_TYPE * cmatval, EGLPNUM_TYPE * obj,
+ EGLPNUM_TYPE * lower, EGLPNUM_TYPE * upper, const char **names, int factorok),
+ EGLPNUM_TYPENAME_ILLlib_delcols ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_basis * B, int num, int *dellist,
+ int *basis_ok),
+ EGLPNUM_TYPENAME_ILLlib_chgcoef ( EGLPNUM_TYPENAME_lpinfo * lp, int rowindex, int colindex, EGLPNUM_TYPE coef),
+ EGLPNUM_TYPENAME_ILLlib_getcoef (EGLPNUM_TYPENAME_lpinfo *lp, int rowindex, int colindex, EGLPNUM_TYPE* coef),
+ EGLPNUM_TYPENAME_ILLlib_chgrange (EGLPNUM_TYPENAME_lpinfo *lp, int indx, EGLPNUM_TYPE coef),
+ EGLPNUM_TYPENAME_ILLlib_chgsense ( EGLPNUM_TYPENAME_lpinfo * lp, int num, int *rowlist, char *sense),
+ EGLPNUM_TYPENAME_ILLlib_getsenses (EGLPNUM_TYPENAME_lpinfo *lp, char *senses),
+ EGLPNUM_TYPENAME_ILLlib_getrows ( EGLPNUM_TYPENAME_lpinfo * lp, int num, int *rowlist, int **rowcnt,
+ int **rowbeg, int **rowind, EGLPNUM_TYPE ** rowval, EGLPNUM_TYPE ** rhs,
+ char **sense, EGLPNUM_TYPE ** range, char ***names),
+ EGLPNUM_TYPENAME_ILLlib_getcols ( EGLPNUM_TYPENAME_lpinfo * lp, int num, int *collist, int **colcnt,
+ int **colbeg, int **colind, EGLPNUM_TYPE ** colval, EGLPNUM_TYPE ** obj,
+ EGLPNUM_TYPE ** lower, EGLPNUM_TYPE ** upper, char ***names),
+ EGLPNUM_TYPENAME_ILLlib_getobj ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPE * obj),
+ EGLPNUM_TYPENAME_ILLlib_getobj_list (EGLPNUM_TYPENAME_lpinfo *lp, int num, int* collist, EGLPNUM_TYPE* obj),
+ EGLPNUM_TYPENAME_ILLlib_chgobj ( EGLPNUM_TYPENAME_lpinfo * lp, int indx, EGLPNUM_TYPE coef),
+ EGLPNUM_TYPENAME_ILLlib_getrhs ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPE * rhs),
+ EGLPNUM_TYPENAME_ILLlib_chgrhs ( EGLPNUM_TYPENAME_lpinfo * lp, int indx, EGLPNUM_TYPE coef),
+ EGLPNUM_TYPENAME_ILLlib_getintflags ( EGLPNUM_TYPENAME_lpinfo * lp, int *intflags),
+ EGLPNUM_TYPENAME_ILLlib_rownames ( EGLPNUM_TYPENAME_lpinfo * lp, char **rownames),
+ EGLPNUM_TYPENAME_ILLlib_colnames ( EGLPNUM_TYPENAME_lpinfo * lp, char **colnames),
+ EGLPNUM_TYPENAME_ILLlib_colindex ( EGLPNUM_TYPENAME_lpinfo * lp, const char *name, int *colindex),
+ EGLPNUM_TYPENAME_ILLlib_rowindex ( EGLPNUM_TYPENAME_lpinfo * lp, const char *name, int *rowindex),
+ EGLPNUM_TYPENAME_ILLlib_chgbnd ( EGLPNUM_TYPENAME_lpinfo * lp, int indx, int lu,const EGLPNUM_TYPE bnd),
+ EGLPNUM_TYPENAME_ILLlib_chgbnds ( EGLPNUM_TYPENAME_lpinfo * lp, int cnt, int *indx, char *lu, const EGLPNUM_TYPE * bnd),
+ EGLPNUM_TYPENAME_ILLlib_getbnd ( EGLPNUM_TYPENAME_lpinfo * lp, int indx, int lu, EGLPNUM_TYPE * bnd),
+ EGLPNUM_TYPENAME_ILLlib_getbnds ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPE * lower, EGLPNUM_TYPE * upper),
+ EGLPNUM_TYPENAME_ILLlib_getbnds_list ( EGLPNUM_TYPENAME_lpinfo *lp, int num, int*collist, EGLPNUM_TYPE *lower,
+ EGLPNUM_TYPE *upper),
+ EGLPNUM_TYPENAME_ILLlib_strongbranch ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_price_info * pinf, int *candidatelist,
+ int ncand, EGLPNUM_TYPE * xlist, EGLPNUM_TYPE * downpen, EGLPNUM_TYPE * uppen,
+ int iterations, EGLPNUM_TYPE objbound, struct itcnt_t*itcnt),
+ EGLPNUM_TYPENAME_ILLlib_getbasis ( EGLPNUM_TYPENAME_lpinfo * lp, char *cstat, char *rstat),
+ EGLPNUM_TYPENAME_ILLlib_loadbasis ( EGLPNUM_TYPENAME_ILLlp_basis * B, int nstruct, int nrows, char *cstat,
+ char *rstat),
+ EGLPNUM_TYPENAME_ILLlib_readbasis ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_basis * B, const char *fname),
+ EGLPNUM_TYPENAME_ILLlib_writebasis ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_basis * B, const char *fname),
+ EGLPNUM_TYPENAME_ILLlib_getrownorms ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_price_info * pinf, EGLPNUM_TYPE * rownorms),
+ EGLPNUM_TYPENAME_ILLlib_loadrownorms ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_price_info * pinf, EGLPNUM_TYPE * rownorms),
+ EGLPNUM_TYPENAME_ILLlib_recompute_rownorms ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_price_info * pinf),
+ EGLPNUM_TYPENAME_ILLlib_iter ( EGLPNUM_TYPENAME_lpinfo * lp),
+ EGLPNUM_TYPENAME_ILLlib_print_x ( EGioFile_t * fd, EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_ILLlp_cache * C, EGLPNUM_TYPE * x,
+ int nonZerosOnly),
+ EGLPNUM_TYPENAME_ILLwrite_lp_file ( EGLPNUM_TYPENAME_ILLlpdata * lp, EGioFile_t * eout, EGLPNUM_TYPENAME_qserror_collector * c);
+
+
+extern int EGLPNUM_TYPENAME_ILLlib_findName (
+ EGLPNUM_TYPENAME_ILLlpdata * qslp,
+ int forRow,
+ const char *name,
+ int id,
+ char buf[ILL_namebufsize]);
+
+/****************************************************************************/
+/* */
+/* presolve.c */
+/* */
+/****************************************************************************/
+
+int EGLPNUM_TYPENAME_ILLpresolve_add_logicals (
+ EGLPNUM_TYPENAME_ILLlpdata * lp);
+
+
+/****************************************************************************/
+/* */
+/* binary.c */
+/* */
+/****************************************************************************/
+
+int EGLPNUM_TYPENAME_ILLmip_binary_dfs (
+ EGLPNUM_TYPENAME_lpinfo * lp);
+
+#endif /* EGLPNUM_TYPENAME_ILL_LIB_H */
diff --git a/qsopt_ex/logging-private.h b/qsopt_ex/logging-private.h
new file mode 100644
index 0000000..9cf9c0e
--- /dev/null
+++ b/qsopt_ex/logging-private.h
@@ -0,0 +1,261 @@
+/* logging - Private functions for logging/error reporting
+ *
+ * Copyright (C) 2015 Jon Lund Steffensen <jonlst at gmail.com>
+ *
+ * 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/>.
+ * */
+
+#ifndef QS_LOGGING_PRIVATE_H__
+#define QS_LOGGING_PRIVATE_H__
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+
+void QSlogv(const char *format, va_list args)
+ __attribute__ ((format(__printf__, 1, 0)));
+void QSlog(const char *format, ...)
+ __attribute__ ((format(__printf__, 1, 0)));
+
+
+/** @name Code Location Utility:
+ * this are utility macros to print information about where we are.
+ * @note For some reason __func__ don't work correctly for sun's cc in inline
+ * functions, so we don't use in SUN architecture */
+/* @{ */
+#define __EG_PRINTLOCF__ QSlog(", in %s (%s:%d)",__func__,__FILE__,__LINE__)
+#define __EG_PRINTLOC__ __EG_PRINTLOCF__
+#define __EG_PRINTLOC2F__ QSlog("in %s (%s:%d)",__func__,__FILE__,__LINE__)
+#define __EG_PRINTLOC2__ __EG_PRINTLOC2F__
+/* @} */
+
+/** @brief if the given display level is over the given treshold, display the
+ * given message and location information */
+#define IFMESSAGE(__display,...) do{\
+ if((__display)>0){\
+ QSlog(__VA_ARGS__); \
+ __EG_PRINTLOC__;}}while(0)
+
+/** @brief if return value is non-zero warn on screen */
+#define WARNIF(__L__) do{\
+ const int __Wval__= (__L__);\
+ if(__Wval__){QSlog("WARNING: In %s (%s:%d) "#__L__" = %d",__func__,__FILE__,__LINE__,__Wval__);}}while(0)
+#if DEBUG>=1
+
+/** @brief This macro is to print error messages and to return with value one
+ * from the current function, it also print the file and line where this
+ * happend, but the condition is looked only if the debug level is at least __L
+ * */
+#define EXITL(__L,__A,...) ({\
+ if(__L<=DEBUG){\
+ if(__A){\
+ QSlog(__VA_ARGS__); \
+ __EG_PRINTLOC__;\
+ _exit(1);}}})
+
+/** @brief This macro is to print error messages and to return with value one
+ * from the current function, it also print the file and line where this
+ * happend, but the condition is looked only if the debug level is at least __L
+ * */
+#define TESTL(__L,__A,...) ({\
+ if(__L<=DEBUG){\
+ if(__A){\
+ QSlog(__VA_ARGS__); \
+ __EG_PRINTLOC__;\
+ return 1;}}})
+
+/** @brief this macro check if the value of a pointer is not bellow the first
+ * 64Kb, if so it return the given value */
+#define PTRTEST(__PTR,__RVAL) {\
+ if(__PTR) ADVTESTL(0,((size_t)(__PTR)) < (1U<<16),__RVAL, \
+ "%s=%p is not a valid pointer",\
+ #__PTR, (void*)(__PTR));}
+
+/** @brief This macro is to print error messages and jump to the given point
+ * in the code, it also print the file and line where this happend */
+#define TESTGL(__L,__A,__B,...) ({\
+ if((__L)<=DEBUG && (__A)){\
+ QSlog("ERROR: " __VA_ARGS__); \
+ __EG_PRINTLOC__;\
+ goto __B;}})
+
+/** @brief return value macro, if the value is non-zero, write to standard
+ * error the returning code and where this happen */
+#define EG_RETURN(__A) {\
+ const int __RVAL__ = (__A);\
+ if(__RVAL__){\
+ QSlog("rval %d",__RVAL__); \
+ __EG_PRINTLOC__;}\
+ return __RVAL__;}
+
+/** @brief This macro is to print error messages and jump to the given point
+ * in the code, it also print the file and line where this happend */
+#define TESTG(__A,__B,...) ({\
+ if(__A){\
+ QSlog("ERROR: " __VA_ARGS__); \
+ __EG_PRINTLOC__;\
+ goto __B;}})
+
+/** @brief This macro is to print error messages and jump to the CLEANUP label
+ * in the current function, it also print the file and line where this happend */
+#define TESTGD(__A,...) ({\
+ if(__A){\
+ QSlog("ERROR: " __VA_ARGS__); \
+ __EG_PRINTLOC__;\
+ goto CLEANUP;}})
+
+/** @brief This macro is to print error messages and to return with value one
+ * from the current function, it also print the file and line where this
+ * happend */
+#define TEST(__A,...) ({\
+ if(__A){\
+ QSlog(__VA_ARGS__); \
+ __EG_PRINTLOC__;\
+ return 1;}})
+
+/** @brief This macro print messages to the screen when the debug level is as
+ * big as the first parameter, if the debug level is zero we eliminate the
+ * code and reduce it to the empty instruction. */
+#define MESSAGEF(__A,...) ({\
+ if(__A <= DEBUG ){\
+ QSlog(__VA_ARGS__); \
+ __EG_PRINTLOCF__(__F);}})
+
+/** @brief This macro print messages to the screen when the debug level is as
+ * big as the first parameter, if the debug level is zero we eliminate the
+ * code and reduce it to the empty instruction. */
+#define MESSAGE(__A,...) ({\
+ if(__A <= DEBUG ){\
+ QSlog(__VA_ARGS__); \
+ __EG_PRINTLOC__;}})
+
+/** @brief This macro print messages to the screen when the verbose level is as
+ * big as the first parameter, if the verbose level is zero we eliminate the
+ * code and reduce it to the empty instruction. */
+#if VERBOSE_LEVEL >= 1
+#define OUTPUT(__A,...) ({\
+ if(__A <= VERBOSE_LEVEL ){\
+ QSlog(__VA_ARGS__);}})
+#else
+#define OUTPUT(__A,...) ;
+#endif
+
+/** @brief This macro print messages to the screen when the condition __A is
+ * true .if the debug level is one we don't print any warning message. if
+ * the debug level is zero we eliminate the code and reduce it to the empty
+ * instruction. */
+#define WARNINGL(__L,__A,...) ({\
+ if((__A)&&(DEBUG>=__L)){\
+ QSlog("WARNING: " __VA_ARGS__);\
+ __EG_PRINTLOC__;}})
+
+#else
+#define TESTL(__L,__A,...) ;
+#define EXITL(__L,__A,...) ;
+#define TEST(__A,...) ;
+#define TESTG(__A,__B,...) ;
+#define TESTGL(__A,__B,...) ;
+#define MESSAGE(__A,...) ;
+#define MESSAGEF(__A,__F,...) ;
+#define WARNINGL(__L,__A,...) ;
+#define EG_RETURN(__A) do{return (__A);}while(0)
+#define PTRTEST(__PTR,__RVAL) ;
+#endif
+
+/** @brief This macro is to print error messages and to return with value one
+ * from the current function, it also print the file and line where this
+ * happend */
+#define FTEST(__A,...) ({\
+ if(__A){\
+ QSlog(__VA_ARGS__); \
+ __EG_PRINTLOC__;\
+ return 1;}})
+
+/** @brief This macro is to print error messages and to return with value one
+ * from the current function, it also print the file and line where this
+ * happend */
+#define FTESTG(__A,__B,...) ({\
+ if(__A){\
+ QSlog("ERROR: " __VA_ARGS__); \
+ __EG_PRINTLOC__;\
+ goto __B;}})
+
+/** @brief This macro print messages to the screen when the condition __A is
+ * true. */
+#define WARNING(__A,...) ({ \
+ if(__A){ \
+ QSlog("WARNING: " __VA_ARGS__); \
+ __EG_PRINTLOC__;}})
+
+/** @brief this macro test if a value is non zero, if it is it print where is
+ * it and exit EXIT_FAILURE. The idea is to use it to check return values of functions,
+ * and the calling function can't return a status, and then we are forced to
+ * exit. */
+#define EXITRVAL(__A) ({\
+ if(__A){\
+ __EG_PRINTLOC2__;\
+ exit(EXIT_FAILURE);}})
+
+/** @brief This macro is to print error messages and exit the program with
+ * code one from the current function, it also print the file and line where
+ * this happend */
+#define EXIT(__A,...) ({ \
+ if(__A){ \
+ QSlog("EXIT: " __VA_ARGS__); \
+ __EG_PRINTLOC__;\
+ exit(EXIT_FAILURE);}})
+
+/** @brief this macro test if a value is non zero, if it is it print where is
+ * it and return __B. The idea is to use it to check return values of functions
+ * */
+#define ADVCHECKRVAL(__A,__B) ({\
+ if(__A){\
+ __EG_PRINTLOC2__;\
+ return __B;}})
+
+/** @brief This macro test a condition '__A' when the debug level used at
+ * compile time is at least '__L'. If the condition is true, it print the
+ * message and return the '__RVAL' value. */
+#define ADVTESTL(__L,__A,__RVAL,...) ({\
+ if((DEBUG>=__L)&&(__A)){\
+ QSlog(__VA_ARGS__); \
+ __EG_PRINTLOC__;\
+ return __RVAL;}})
+
+/** @brief this macro test if a value is non zero, if it is it print where is
+ * it and return 1. The idea is to use it to check return values of functions
+ * */
+#define CHECKRVAL(__A) ({\
+ if(__A){\
+ __EG_PRINTLOC2__;\
+ return __A;}})
+
+/** @brief, if a non-zero value is given as an argument, check the errno stored
+ * in the system, print the related message, and return the non-zero given
+ * parameter, otherwise, do nothing.
+ * @param __value if non-zero check systems errors, and return this value
+ * */
+#define TESTERRNOIF(__value) do{\
+ if(__value){\
+ const int __EGserrno = errno;\
+ QSlog("failed with errno %d, %s",__EGserrno, strerror(__EGserrno)); \
+ __EG_PRINTLOC2__;\
+ return __value;}}while(0)
+
+/** @brief this function, if the input is non zero, print a message of
+ * function, file and line and then goto the second parameter */
+#define CHECKRVALG(__A,__B) do{if(__A){__EG_PRINTLOC2__;goto __B;}}while(0)
+
+#endif /* ! QS_LOGGING_PRIVATE_H__ */
diff --git a/qsopt_ex/logging.c b/qsopt_ex/logging.c
new file mode 100644
index 0000000..9abe1a4
--- /dev/null
+++ b/qsopt_ex/logging.c
@@ -0,0 +1,82 @@
+/* logging - Functions for logging/error reporting
+ *
+ * Copyright (C) 2015 Jon Lund Steffensen <jonlst at gmail.com>
+ *
+ * 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/>.
+ * */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "logging.h"
+#include "logging-private.h"
+
+
+static QSlog_func global_log_func = NULL;
+static void *global_log_data = NULL;
+
+
+void QSlog_set_handler(QSlog_func log_func, void *data)
+{
+ global_log_func = log_func;
+ global_log_data = data;
+}
+
+void QSlogv(const char *format, va_list args)
+{
+ va_list args2;
+ va_copy(args2, args);
+
+ int n = vsnprintf(NULL, 0, format, args2);
+ if (n < 0) {
+ perror("vsnprintf");
+ abort();
+ }
+
+ va_end(args2);
+
+ char *buffer = malloc(n+1);
+ if (buffer == NULL) {
+ perror("malloc");
+ abort();
+ }
+
+ n = vsnprintf(buffer, n+1, format, args);
+ if (n < 0) {
+ perror("vsnprintf");
+ free(buffer);
+ abort();
+ }
+
+ if (global_log_func != NULL) {
+ global_log_func(buffer, global_log_data);
+ } else {
+ fprintf(stderr, "%s\n", buffer);
+ }
+
+ free(buffer);
+}
+
+void QSlog(const char *format, ...)
+{
+ va_list args;
+ va_start(args, format);
+ QSlogv(format, args);
+ va_end(args);
+}
diff --git a/qsopt_ex/logging.h b/qsopt_ex/logging.h
new file mode 100644
index 0000000..bd79629
--- /dev/null
+++ b/qsopt_ex/logging.h
@@ -0,0 +1,26 @@
+/* logging - Functions for logging/error reporting
+ *
+ * Copyright (C) 2015 Jon Lund Steffensen <jonlst at gmail.com>
+ *
+ * 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/>.
+ * */
+
+#ifndef QS_LOGGING_H__
+#define QS_LOGGING_H__
+
+typedef void (*QSlog_func)(const char *message, void *data);
+
+void QSlog_set_handler(QSlog_func log_func, void *data);
+
+#endif /* ! QS_LOGGING_H__ */
diff --git a/qsopt_ex/lp.c b/qsopt_ex/lp.c
new file mode 100644
index 0000000..73c6fc3
--- /dev/null
+++ b/qsopt_ex/lp.c
@@ -0,0 +1,1280 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: lp.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+
+/****************************************************************************/
+/* */
+/* Routines for Reading and Writing LP Files */
+/* */
+/* EXPORTED FUNCTIONS */
+/* */
+/* int EGLPNUM_TYPENAME_ILLwrite_lp (EGioFile_t *out, EGLPNUM_TYPENAME_ILLlpdata *lp) */
+/* int EGLPNUM_TYPENAME_ILLread_lp (EGLPNUM_TYPENAME_qsline_reader f, const char *fname, EGLPNUM_TYPENAME_rawlpdata *lp)*/
+/* int EGLPNUM_TYPENAME_ILLis_lp_name_char (char c, int pos) */
+/* int EGLPNUM_TYPENAME_ILLread_constraint_expr(EGLPNUM_TYPENAME_ILLread_lp_state *state, */
+/* EGLPNUM_TYPENAME_rawlpdata *lp, int rowind, int allowNew) */
+/* int EGLPNUM_TYPENAME_ILLread_constraint_name (EGLPNUM_TYPENAME_ILLread_lp_state *state, */
+/* char **rowname) */
+/* int EGLPNUM_TYPENAME_ILLread_one_constraint (EGLPNUM_TYPENAME_ILLread_lp_state *state, */
+/* const char *rowname, EGLPNUM_TYPENAME_rawlpdata *lp, int allowNewCols) */
+/* */
+/****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "eg_lpnum.h"
+#include "eg_io.h"
+#include "except.h"
+#include "names.h"
+#include "util.h"
+
+/* from the cplex manual:
+
+ not exceed 16 characters, all of which must be alphanumeric
+ (a-z, A-Z, 0-9) or one of these symbols: ! " # $ % & ( ) / ,
+ . ; ? @ _ ` ' { } | ~. Longer names will be truncated to 16
+ characters. A variable name can not begin with a number or a
+ period.
+
+ The letter E or e, alone or followed by other valid symbols,
+ or followed by another E or e, should be avoided as this
+ notation is reserved for exponential entries. Thus, variables
+ can not be named e9, E-24, E8cats, or other names that could
+ be interpreted as an exponent. Even variable names such as
+ eels or example can cause a read error, depending on their
+ placement in an input line.
+
+ Also, the following characters are not valid in variable
+ names (in order to allow for quadratic objective
+ information): ^, *, [ and ].
+*/
+/* OUR DEFINTION:
+ * -) variables consist of a-z A-Z 0-9 !"#$%(),;.?@_`'{}|~
+ * don't start with a digit or '.'
+ * return 0 for variable
+ * return -1 for keyword
+ * return 1 otherwise
+ */
+
+
+int EGLPNUM_TYPENAME_ILLis_lp_name_char (
+ int c,
+ int pos)
+{
+ return ((('a' <= c) && (c <= 'z')) ||
+ (('A' <= c) && (c <= 'Z')) ||
+ ((pos > 0) && ('0' <= c) && (c <= '9')) ||
+ ((pos > 0) && (c == '.')) ||
+ (strchr ("!\"#$%&()/,;?@_`'{}|~", c) != NULL));
+}
+
+
+/*
+ * -) anything after '\' is comment
+ * -) Problem is optional and comes first
+ * -) Minimize, Maximize, ... comes after Problem
+ * -) variables consist of a-z A-Z 0-9!"#$%(),;.?@_`'{}|~
+ */
+
+/* NOTES */
+/*
+ * don't start with a digit or '.'
+ */
+
+static const int LINE_LEN = 256;
+
+#include "lp_EGLPNUM_TYPENAME.h"
+#include "rawlp_EGLPNUM_TYPENAME.h"
+#include "read_lp_EGLPNUM_TYPENAME.h"
+#include "write_lp_EGLPNUM_TYPENAME.h"
+
+//extern EGLPNUM_TYPE EGLPNUM_TYPENAME_SZERO_TOLER;
+static int TRACE = 0;
+
+static int read_problem_name (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp);
+static int read_minmax (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp);
+static int read_objective (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp);
+static int read_objective (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp);
+static int read_constraints (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ int allowNewCols);
+static int read_colname (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ ILLsymboltab * coltab,
+ int mustHave);
+static int read_integer (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp);
+static int read_bounds (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp);
+static int add_var (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ EGLPNUM_TYPE coef,
+ int row,
+ int allowNew);
+
+/*------------------------------------------------------------------------
+ * EGLPNUM_TYPENAME_ILLwrite_lp and support routines
+ */
+static int fix_names (
+ EGLPNUM_TYPENAME_qserror_collector * collector,
+ char **names,
+ int nnames,
+ const char *extra,
+ int prefix,
+ char ***newnames);
+static void write_objective (
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ const char *objname,
+ char **colnames);
+static int write_row (
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ EGLPNUM_TYPENAME_ILLlp_rows * lprows,
+ int i,
+ char **rownames,
+ char **colnames,
+ int *colInRow,
+ EGLPNUM_TYPE * colCoef);
+static int write_bounds (
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ char **colnames);
+static void write_intvars (
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ char **colnames);
+
+int EGLPNUM_TYPENAME_ILLwrite_lp (
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ EGLPNUM_TYPENAME_qserror_collector * collector)
+{
+ int rval = 0;
+ int i;
+ EGLPNUM_TYPENAME_ILLlp_rows lp_rows, *lprows = NULL;
+ char **colnames = (char **) NULL;
+ char **rownames = (char **) NULL;
+ EGLPNUM_TYPE *colCoef = NULL;
+ int *colInRow = NULL;
+ const char *objname;
+
+ ILL_FAILfalse (lp, "called without data\n");
+ if (lp->nstruct == 0 || lp->nrows == 0)
+ {
+ EG_RETURN (rval);
+ }
+ ILL_FAILfalse (lp->colnames != NULL, "lp->colnames != NULL");
+ ILL_FAILfalse (lp->rownames != NULL, "lp->rownames != NULL");
+ ILL_FAILfalse (lp->nstruct == lp->coltab.tablesize,
+ "lp coltab has nstruct entries");
+ if (lp->objname == (char *) NULL)
+ {
+ ILL_FAILfalse (lp->nrows == lp->rowtab.tablesize,
+ "lp rowtab should have nrows entries");
+ }
+ else
+ {
+ ILL_FAILfalse (lp->nrows + 1 == lp->rowtab.tablesize,
+ "lp rowtab should have nrows+1 entries");
+ ILL_FAILfalse (ILLsymboltab_contains (&lp->rowtab, lp->objname),
+ "rowtab must contain objname");
+ }
+
+ rval = fix_names (collector, lp->colnames, lp->nstruct, NULL, 'x', &colnames);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = fix_names (collector, lp->rownames, lp->nrows,
+ (lp->objname) ? lp->objname : "obj", 'c', &rownames);
+ CHECKRVALG (rval, CLEANUP);
+ objname = rownames[lp->nrows];
+
+ ILL_FAILtrue (objname == NULL, "OOps, that should never happen");
+ CHECKRVALG (rval, CLEANUP);
+
+ if (lp->sos.matcols > 0)
+ {
+ rval +=
+ EGLPNUM_TYPENAME_ILLdata_error (collector, "Can't express SOS information in LP format.");
+ }
+
+ write_objective (lp, objname, colnames);
+
+ /* Note, EGLPNUM_TYPENAME_ILLlp_rows_init returns cols ordered by structmap, so we may use
+ * colnames[i] when pulling i from the matrix data. */
+
+ lprows = &lp_rows;
+ if (EGLPNUM_TYPENAME_ILLlp_rows_init (lprows, lp, 0) != 0)
+ {
+ rval += 1;
+ ILL_FAILtrue (rval, "EGLPNUM_TYPENAME_ILLlp_rows_init failed\n");
+ }
+
+ colCoef = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nstruct);
+ ILL_SAFE_MALLOC (colInRow, lp->nstruct, int);
+
+ for (i = 0; i < lp->nstruct; i++)
+ {
+ colInRow[i] = -1;
+ }
+
+ EGLPNUM_TYPENAME_ILLprint_report (lp, "Subject To\n");
+ for (i = 0; i < lp->nrows; i++)
+ {
+ if (lprows->rowcnt[i] == 0)
+ {
+ /*
+ * EGLPNUM_TYPENAME_ILLdata_warn (collector, "Not printing empty row \"%s\".", rownames[i]);
+ */
+ continue;
+ }
+ rval += write_row (lp, lprows, i, rownames, colnames, colInRow, colCoef);
+ }
+
+ rval += write_bounds (lp, colnames);
+
+ if (lp->intmarker != NULL)
+ {
+ write_intvars (lp, colnames);
+ }
+
+ EGLPNUM_TYPENAME_ILLprint_report (lp, "End\n");
+CLEANUP:
+ if (lprows != NULL)
+ {
+ EGLPNUM_TYPENAME_ILLlp_rows_clear (lprows);
+ }
+ ILLfree_names (colnames, lp->nstruct);
+ ILLfree_names (rownames, lp->nrows + 1);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (colCoef);
+ ILL_IFFREE (colInRow, int);
+
+ EG_RETURN (rval);
+}
+
+static void write_objective (
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ const char *objname,
+ char **colnames)
+{
+ int ri, i, k, var;
+ EGLPNUM_TYPENAME_ILLwrite_lp_state ln, *line = &ln;
+
+ if (lp->probname != NULL)
+ {
+ EGLPNUM_TYPENAME_ILLprint_report (lp, "Problem\n %s\n", lp->probname);
+ }
+ if (lp->objsense == EGLPNUM_TYPENAME_ILL_MIN)
+ {
+ EGLPNUM_TYPENAME_ILLprint_report (lp, "Minimize\n");
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_ILLprint_report (lp, "Maximize\n");
+ }
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_init (line, NULL);
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " ");
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, objname);
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, ": ");
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_save_start (line);
+
+ for (ri = 0, var = 0; ri < lp->nstruct; ri++)
+ {
+ i = lp->structmap[ri];
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (lp->obj[i]))
+ {
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append_coef (line, lp->obj[i], var);
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " ");
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, colnames[ri]);
+ var++;
+
+ /* we put a least 4 terms on a line
+ * and then we stop after LINE_LEN or more characters
+ */
+ if ((line->total >= LINE_LEN) && (var >= 4))
+ {
+ /* see whether there is another term
+ * if so append a '+' and print line */
+ k = ri + 1;
+ while (k < lp->nstruct)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (lp->obj[lp->structmap[k]]))
+ {
+ break;
+ }
+ else
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (lp->obj[lp->structmap[k]]))
+ {
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " +");
+ break;
+ }
+ }
+ k++;
+ }
+ var = 0; /* next line does not need to prefix coef with '+' */
+ EGLPNUM_TYPENAME_ILLprint_report (lp, "%s\n", line->buf);
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_start (line);
+ }
+ }
+ }
+ if (var > 0)
+ {
+ EGLPNUM_TYPENAME_ILLprint_report (lp, "%s\n", line->buf);
+ }
+}
+
+static void write_the_expr (
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ EGLPNUM_TYPENAME_ILLwrite_lp_state * line,
+ char *rowname,
+ EGLPNUM_TYPENAME_ILLlp_rows * lprows,
+ int row,
+ char **colnames,
+ int *colInRow,
+ EGLPNUM_TYPE * colCoef,
+ int ncols)
+{
+ int var, firstVar, k, i;
+ EGLPNUM_TYPE *coef;
+
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_init (line, NULL);
+ if (rowname != NULL)
+ {
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " ");
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, rowname);
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, ": ");
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " ");
+ }
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_save_start (line);
+
+ for (k = lprows->rowbeg[row];
+ k < lprows->rowbeg[row] + lprows->rowcnt[row]; k++)
+ {
+ i = lprows->rowind[k];
+ colInRow[i] = row;
+ EGLPNUM_TYPENAME_EGlpNumCopy (colCoef[i], lprows->rowval[k]);
+ }
+ var = 0;
+ firstVar = 1;
+ for (i = 0; i < ncols; i++)
+ {
+ if (colInRow[i] == row)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (colCoef[i]))
+ {
+ coef = &(colCoef[i]);
+ if (line->total >= LINE_LEN)
+ {
+ EGLPNUM_TYPENAME_ILLprint_report (lp, "%s\n", line->buf);
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_start (line);
+ if ((!firstVar) && !EGLPNUM_TYPENAME_EGlpNumIsLessZero (*coef))
+ {
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " +");
+ }
+ var = 0;
+ }
+
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append_coef (line, *coef, var);
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " ");
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, colnames[i]);
+ var++;
+ firstVar = 0;
+ }
+ }
+ }
+}
+
+static int write_row (
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ EGLPNUM_TYPENAME_ILLlp_rows * lprows,
+ int i,
+ char **rownames,
+ char **colnames,
+ int *colInRow,
+ EGLPNUM_TYPE * colCoef)
+{
+ EGLPNUM_TYPENAME_ILLwrite_lp_state ln, *line = &ln;
+ int rval = 0;
+ EGLPNUM_TYPE ntmp;
+
+ write_the_expr (lp, line, rownames[i], lprows, i, colnames,
+ colInRow, colCoef, lp->nstruct);
+
+ switch (lp->sense[i])
+ {
+ case 'G':
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " >= ");
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append_number (line, lp->rhs[i]);
+ break;
+ case 'L':
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " <= ");
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append_number (line, lp->rhs[i]);
+ break;
+ case 'E':
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " = ");
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append_number (line, lp->rhs[i]);
+ break;
+ case 'R':
+ ILL_FAILtrue (!lp->rangeval, "RANGE constraints without values\n");
+ EGLPNUM_TYPENAME_EGlpNumInitVar (ntmp);
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " >= ");
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append_number (line, lp->rhs[i]);
+
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " \t\\ RANGE (");
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append_number (line, lp->rhs[i]);
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, ", ");
+ EGLPNUM_TYPENAME_EGlpNumCopySum (ntmp, lp->rhs[i], lp->rangeval[i]);
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append_number (line, ntmp);
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, ")");
+ EGLPNUM_TYPENAME_ILLprint_report (lp, "%s\n", line->buf);
+
+ write_the_expr (lp, line, NULL, lprows, i,
+ colnames, colInRow, colCoef, lp->nstruct);
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " <= ");
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append_number (line, ntmp);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+ break;
+ default:
+ ILL_FAILtrue (1, "Unknown row sense\n");
+ }
+
+ EGLPNUM_TYPENAME_ILLprint_report (lp, "%s\n", line->buf);
+CLEANUP:
+ EG_RETURN (rval);
+}
+
+static int write_bounds (
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ char **colnames)
+{
+ int ri, i, rval = 0;
+ int prtLower, prtUpper;
+ EGLPNUM_TYPENAME_ILLwrite_lp_state l, *line = &l;
+
+ ILL_FAILtrue (lp->lower == NULL || lp->upper == NULL,
+ "Should not call write_bounds when lower or upper are NULL");
+ ri = EGLPNUM_TYPENAME_ILLraw_first_nondefault_bound (lp);
+ if (ri != lp->nstruct)
+ {
+ EGLPNUM_TYPENAME_ILLprint_report (lp, "Bounds\n");
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_init (line, " ");
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_save_start (line);
+
+ for (; ri < lp->nstruct; ri++)
+ {
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_start (line);
+ i = lp->structmap[ri];
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (lp->lower[i], lp->upper[i]))
+ {
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " ");
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, colnames[ri]);
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " = ");
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append_number (line, lp->upper[i]);
+ EGLPNUM_TYPENAME_ILLprint_report (lp, "%s\n", line->buf);
+ continue;
+ }
+ if ((EGLPNUM_TYPENAME_EGlpNumIsEqqual (lp->lower[i], EGLPNUM_TYPENAME_ILL_MINDOUBLE)) &&
+ (EGLPNUM_TYPENAME_EGlpNumIsEqqual (lp->upper[i], EGLPNUM_TYPENAME_ILL_MAXDOUBLE)))
+ {
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, colnames[ri]);
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " free");
+ EGLPNUM_TYPENAME_ILLprint_report (lp, "%s\n", line->buf);
+ continue;
+ }
+ prtLower = !EGLPNUM_TYPENAME_ILLraw_default_lower (lp, i);
+ prtUpper = !EGLPNUM_TYPENAME_ILLraw_default_upper (lp, i, ri);
+ if (prtLower || prtUpper)
+ {
+ if (prtLower)
+ {
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append_number (line, lp->lower[i]);
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " <= ");
+ }
+ if (prtLower || prtUpper)
+ {
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, colnames[ri]);
+ }
+ if (prtUpper)
+ {
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " <= ");
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append_number (line, lp->upper[i]);
+ }
+ EGLPNUM_TYPENAME_ILLprint_report (lp, "%s\n", line->buf);
+ }
+ }
+ }
+CLEANUP:
+ EG_RETURN (rval);
+}
+
+static void write_intvars (
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ char **colnames)
+{
+ EGLPNUM_TYPENAME_ILLwrite_lp_state ln, *line = &ln;
+ int var, j;
+
+ EGLPNUM_TYPENAME_ILLprint_report (lp, "Integer\n");
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_init (line, " ");
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_save_start (line);
+
+ for (j = 0, var = 0; j < lp->nstruct; j++)
+ {
+ if (lp->intmarker[j])
+ {
+ if (var > 0)
+ {
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, " ");
+ }
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, colnames[j]);
+ var++;
+ if (line->total >= LINE_LEN)
+ {
+ EGLPNUM_TYPENAME_ILLprint_report (lp, "%s\n", line->buf);
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_init (line, " ");
+ var = 0;
+ }
+ }
+ }
+ if (var > 0)
+ {
+ EGLPNUM_TYPENAME_ILLprint_report (lp, "%s\n", line->buf);
+ }
+}
+
+/* ------------------------------------------------------------ */
+/* fix up names that are numbers, i.e. prefix with x X x_ or X_ */
+
+/*
+ * redefine names that start with [0-9]; i.e. give a prefix of
+ * "x" | "X" | "x_" | "X_"
+ * or if all these are already taken prefix with "X"<number>
+ * make sure names contain solely the characters:
+ * [a-zA-Z0-9] and ! " # $ % & ( ) / , . ; ? @ _ ` ' { } | ~
+ * rename names with 'bad' chars to <x X x_ X_><number>
+ */
+static int fix_names (
+ EGLPNUM_TYPENAME_qserror_collector * collector,
+ char **names,
+ int nnames,
+ const char *extra,
+ int pref,
+ char ***newnames)
+{
+ ILLsymboltab symt, *symtab = NULL;
+ int rval = 0, i, j, n, ind, hit;
+ char **n_names = NULL;
+ const char *old_name;
+ char buf[ILL_namebufsize];
+ char p1[2], p2[3];
+
+ p1[0] = pref;
+ p1[1] = '\0';
+ p2[0] = pref;
+ p2[1] = '_';
+ p2[2] = '\0';
+
+ ILL_SAFE_MALLOC (n_names, nnames + 1, char *);
+
+ for (i = 0; i < nnames; i++)
+ {
+ n_names[i] = (char *) NULL;
+ }
+
+ for (i = 0; i <= nnames; i++)
+ {
+ if (i == nnames)
+ {
+ if (extra == NULL)
+ break;
+ old_name = extra;
+ }
+ else
+ old_name = names[i];
+
+ n = strlen (old_name);
+ strcpy (buf, old_name);
+ if (!EGLPNUM_TYPENAME_ILLis_lp_name_char (buf[0], 1))
+ {
+ sprintf (buf, "%d", i);
+ }
+ else
+ {
+ for (j = 1; j < n; j++)
+ {
+ if (!EGLPNUM_TYPENAME_ILLis_lp_name_char (buf[j], j))
+ {
+ sprintf (buf, "%d", i);
+ break;
+ }
+ }
+ }
+
+ if (!EGLPNUM_TYPENAME_ILLis_lp_name_char (buf[0], 0))
+ {
+ if (symtab == NULL)
+ {
+ symtab = &symt;
+ ILLsymboltab_init (symtab);
+ ILLsymboltab_create (symtab, nnames + 1);
+ for (j = 0; j < nnames; j++)
+ {
+ ILLsymboltab_register (symtab, names[j], -1, &ind, &hit);
+ ILL_FAILfalse (ind == j, "ind == j");
+ }
+ if (extra != NULL)
+ ILLsymboltab_register (symtab, extra, -1, &ind, &hit);
+ }
+ rval = ILLsymboltab_uname (symtab, buf, p1, p2);
+ CHECKRVALG (rval, CLEANUP);
+ rval = ILLsymboltab_rename (symtab, i, buf);
+ CHECKRVALG (rval, CLEANUP);
+
+ ILL_UTIL_STR (n_names[i], buf);
+ EGLPNUM_TYPENAME_ILLdata_warn (collector,
+ "\"%s\" is not a valid name in LP format; %s\"%s\".",
+ old_name, "renaiming to ", buf);
+ }
+ else
+ {
+ ILL_UTIL_STR (n_names[i], old_name);
+ }
+ }
+
+CLEANUP:
+ if (symtab != NULL)
+ {
+ ILLsymboltab_free (symtab);
+ }
+ *newnames = n_names;
+ EG_RETURN (rval);
+}
+
+/*
+ * end ILLlpdata_lpwrite
+ * ---------------------------------------------------------------------- */
+
+int EGLPNUM_TYPENAME_ILLread_lp (
+ EGLPNUM_TYPENAME_qsline_reader * file,
+ const char *fname,
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+/* file format:
+ * optional problem name (this is in addition to the bix format)
+ * min or max
+ * objective fct
+ * constraints (mandatory !)
+ * optional bounds
+ * optional integer (also new)
+ *
+ * as opposed to the official bix-format:
+ * no blanks in variable names
+ * there may be several bound defs on the same line;
+ * bound definitions may cross line boundaries
+ * constraints that have no name get generated names:
+ * if constraint i has not name we take the first name from the
+ * following list that is not in use:
+ * c<i>, C<i>, or c<i>_0, c<i>_1, c<i>_2, ...
+ */
+ int rval = 0;
+ EGLPNUM_TYPENAME_ILLread_lp_state lpstate, *state = &lpstate;
+
+ const char *bnds[3], *integer[3], *end[2];
+
+ bnds[0] = "BOUNDS";
+ bnds[1] = "BOUND";
+ bnds[2] = NULL;
+ integer[0] = "INTEGER";
+ integer[1] = "INT";
+ integer[2] = NULL;
+ end[0] = "END";
+ end[1] = NULL;
+
+ rval = EGLPNUM_TYPENAME_ILLread_lp_state_init (state, file, fname, 0);
+ CHECKRVALG (rval, CLEANUP);
+
+ EGLPNUM_TYPENAME_ILLinit_rawlpdata (lp, file->error_collector);
+ rval = ILLsymboltab_create (&lp->rowtab, 100) ||
+ ILLsymboltab_create (&lp->coltab, 100);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (EGLPNUM_TYPENAME_ILLread_lp_state_next_field (state))
+ {
+ rval = EGLPNUM_TYPENAME_ILLlp_error (state, "Empty file.\n");
+ }
+ if (rval == 0)
+ rval = read_problem_name (state, lp);
+ if (rval == 0)
+ rval = read_minmax (state, lp);
+ if (rval == 0)
+ rval = read_objective (state, lp);
+ if (rval == 0)
+ rval = read_constraints (state, lp, 1);
+ if ((rval == 0) && (lp->ncols == 0 || lp->nrows == 0))
+ {
+ rval = EGLPNUM_TYPENAME_ILLlp_error (state,
+ "Problem must contain at least one %s.\n",
+ "non empty constraint");
+ }
+ CHECKRVALG (rval, CLEANUP);
+
+ if (EGLPNUM_TYPENAME_ILLread_lp_state_keyword (state, bnds) == 0)
+ {
+ rval = read_bounds (state, lp);
+ }
+ CHECKRVALG (rval, CLEANUP);
+
+ if (EGLPNUM_TYPENAME_ILLread_lp_state_keyword (state, integer) == 0)
+ {
+ rval = read_integer (state, lp);
+ }
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLread_lp_state_keyword (state, end);
+ if (rval != 0)
+ {
+ if (state->eof)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlp_error (state, "Missing \"End\" at end of file.\n");
+ }
+ else
+ {
+ rval = EGLPNUM_TYPENAME_ILLlp_error (state, "\"%s\" unknown keyword\n", state->field);
+ }
+ }
+ if (rval == 0)
+ {
+ rval = EGLPNUM_TYPENAME_ILLraw_fill_in_rownames (lp) || EGLPNUM_TYPENAME_ILLraw_fill_in_bounds (lp);
+ }
+
+CLEANUP:
+ EGLPNUM_TYPENAME_EGlpNumClearVar (lpstate.bound_val);
+ EG_RETURN (rval);
+}
+
+static int read_problem_name (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+ int rval = 0;
+
+ if (!state->fieldOnFirstCol)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlp_error (state,
+ "Keyword \"%s\" not at beginning of line.\n",
+ state->field);
+ }
+ if (!ILLutil_strcasecmp (state->field, "PROBLEM") ||
+ !ILLutil_strcasecmp (state->field, "PROB"))
+ {
+ if (EGLPNUM_TYPENAME_ILLread_lp_state_next_field (state) != 0)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlp_error (state, "No Problem name field.\n");
+ }
+ else
+ {
+ ILL_IFFREE (lp->name, char);
+
+ ILL_UTIL_STR (lp->name, state->field);
+ ILL_IFTRACE ("ProblemName: %s\n", state->field);
+ (void) EGLPNUM_TYPENAME_ILLread_lp_state_next_field (state);
+ }
+ }
+CLEANUP:
+ EG_RETURN (rval);
+}
+
+static int read_minmax (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+ int rval = 0;
+
+ if (!state->fieldOnFirstCol)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlp_error (state,
+ "Keyword \"%s\" not at beginning of line.\n",
+ state->field);
+ }
+ if (!ILLutil_strcasecmp (state->field, "MAX") ||
+ !ILLutil_strcasecmp (state->field, "MAXIMUM") ||
+ !ILLutil_strcasecmp (state->field, "MAXIMIZE"))
+ {
+ lp->objsense = EGLPNUM_TYPENAME_ILL_MAX;
+ }
+ else
+ {
+ if (!ILLutil_strcasecmp (state->field, "MIN") ||
+ !ILLutil_strcasecmp (state->field, "MINIMUM") ||
+ !ILLutil_strcasecmp (state->field, "MINIMIZE"))
+ {
+ lp->objsense = EGLPNUM_TYPENAME_ILL_MIN;
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_ILLread_lp_state_prev_field (state);
+ rval = EGLPNUM_TYPENAME_ILLlp_error (state, "Expecting \"%s\" or \"%s\" keyword.\n",
+ "Minimize", "Maximize");
+ }
+ }
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLread_constraint_expr (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ int rowind,
+ int allowNew)
+{
+ int rval = 0;
+ char firstTerm, haveCoef;
+ const char *name;
+ EGLPNUM_TYPE sign, coef;
+ EGLPNUM_TYPE ntmp;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (ntmp);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (sign);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (coef);
+
+ firstTerm = 1;
+ while (1)
+ {
+ if (EGLPNUM_TYPENAME_ILLread_lp_state_sign (state, &sign) != 0)
+ {
+ if (!firstTerm)
+ {
+ break; /* we've ssen at least one term,
+ * this is the constraint's end */
+ }
+ }
+ haveCoef = EGLPNUM_TYPENAME_ILLread_lp_state_possible_coef (state, &coef, EGLPNUM_TYPENAME_oneLpNum);
+ if (EGLPNUM_TYPENAME_ILLread_lp_state_next_var (state) == 0)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (ntmp, coef);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (ntmp, sign);
+ rval = add_var (lp, state, ntmp, rowind, allowNew);
+ CHECKRVALG (rval, CLEANUP);
+ }
+ else
+ {
+ if (haveCoef == 0)
+ {
+ return EGLPNUM_TYPENAME_ILLlp_error (state, "Coefficient without variable.\n");
+ }
+ else
+ {
+ break;
+ }
+ }
+ firstTerm = 0;
+ }
+CLEANUP:
+ if ((rval == 0) && firstTerm)
+ {
+ name = EGLPNUM_TYPENAME_ILLraw_rowname (lp, rowind);
+ if (name != NULL)
+ {
+ EGLPNUM_TYPENAME_ILLlp_warn (state,
+ "No terms in constraint expression for \"%s\".\n", name);
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_ILLlp_warn (state, "No terms in constraint expression.\n");
+ }
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (sign);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (coef);
+ EG_RETURN (rval);
+}
+
+static int read_objective (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+ int rval = 0;
+ char objname[ILL_namebufsize];
+ char *name;
+
+ ILL_FAILfalse (lp->nrows == 0, "objective should be first row");
+ EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (state, 1);
+ if (EGLPNUM_TYPENAME_ILLread_lp_state_has_colon (state))
+ {
+ if (EGLPNUM_TYPENAME_ILLread_lp_state_next_var (state) != 0)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlp_error (state, "Bad objective function name.\n");
+ }
+ name = state->field;
+ if (rval == 0)
+ {
+ if (EGLPNUM_TYPENAME_ILLread_lp_state_colon (state) != 0)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlp_error (state, "':' must follow constraint row name.\n");
+ }
+ }
+ }
+ else
+ {
+ name = NULL;
+ }
+
+ if (rval == 0)
+ {
+ ILL_FAILfalse (lp->rowtab.tablesize == 0,
+ "objective row is first in symbol tab");
+ if (name == NULL)
+ {
+ strcpy (objname, "obj");
+ EGLPNUM_TYPENAME_ILLlp_warn (state, "Empty obj name; using \"%s\".\n", objname);
+ }
+ else
+ {
+ strcpy (objname, name);
+ }
+ rval = EGLPNUM_TYPENAME_ILLraw_add_row (lp, objname, 'N', EGLPNUM_TYPENAME_zeroLpNum);
+ lp->objindex = lp->nrows - 1;
+ CHECKRVALG (rval, CLEANUP);
+ rval = EGLPNUM_TYPENAME_ILLread_constraint_expr (state, lp, lp->objindex, 1);
+ }
+CLEANUP:
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLread_constraint_name (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ char **rowname)
+{
+ int rval = 0;
+
+ *rowname = NULL;
+
+ /* if there is a ':' on the line: look for constraint row name */
+ if (EGLPNUM_TYPENAME_ILLread_lp_state_has_colon (state))
+ {
+ if (EGLPNUM_TYPENAME_ILLread_lp_state_next_var (state) != 0)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlp_error (state, "Bad constraint row name.\n");
+ }
+ else
+ {
+ *rowname = state->field;
+ if (EGLPNUM_TYPENAME_ILLread_lp_state_colon (state) != 0)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlp_error (state, "':' must follow constraint row name.\n");
+ }
+ }
+ }
+ return rval;
+}
+
+int EGLPNUM_TYPENAME_ILLread_one_constraint (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ const char *rowname,
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ int allowNewCols)
+{
+ int rval = 0;
+ int rowind;
+ char sense;
+ EGLPNUM_TYPE d;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (d);
+
+ if ((rowname != NULL) &&
+ (ILLsymboltab_lookup (&lp->rowtab, rowname, &rowind) == 0))
+ {
+ rval = EGLPNUM_TYPENAME_ILLlp_error (state, "Repeated row name \"%s\".\n", rowname);
+ CHECKRVALG (rval, CLEANUP);
+ }
+ rowind = lp->nrows;
+ rval = rval || EGLPNUM_TYPENAME_ILLraw_add_row (lp, rowname, 'N', EGLPNUM_TYPENAME_zeroLpNum);
+
+ rval = rval || EGLPNUM_TYPENAME_ILLread_constraint_expr (state, lp, rowind, allowNewCols);
+ rval = rval || EGLPNUM_TYPENAME_ILLread_lp_state_sense (state);
+ sense = state->sense_val;
+ if (rval == 0)
+ {
+ rval = EGLPNUM_TYPENAME_ILLread_lp_state_value (state, &d);
+ if (rval)
+ {
+ (void) EGLPNUM_TYPENAME_ILLlp_error (state, "No right hand side value in constraint.\n");
+ }
+ }
+ if (rval == 0)
+ {
+ lp->rowsense[rowind] = sense;
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->rhs[rowind], d);
+ ILL_IFTRACE ("SENSE \"%s\": %c %f\n",
+ EGLPNUM_TYPENAME_ILLraw_rowname (lp, rowind), sense, EGLPNUM_TYPENAME_EGlpNumToLf (d));
+ }
+CLEANUP:
+ EGLPNUM_TYPENAME_EGlpNumClearVar (d);
+ EG_RETURN (rval);
+}
+
+static int read_constraints (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ int allowNewCols)
+{
+ int rval = 0;
+ char *rowname = NULL;
+
+ if (EGLPNUM_TYPENAME_ILLcheck_subject_to (state) != 0)
+ {
+ return EGLPNUM_TYPENAME_ILLlp_error (state, "Constraint section expected.\n");
+ }
+ while (rval == 0)
+ {
+ rval = EGLPNUM_TYPENAME_ILLread_constraint_name (state, &rowname);
+ if (rval == 0)
+ {
+ rval = EGLPNUM_TYPENAME_ILLread_one_constraint (state, rowname, lp, allowNewCols);
+ }
+ if (rval == 0)
+ {
+ if (EGLPNUM_TYPENAME_ILLread_lp_state_next_constraint (state) != 0)
+ {
+ break;
+ }
+ }
+ }
+ EGLPNUM_TYPENAME_ILLread_lp_state_next_field (state);
+ EG_RETURN (rval);
+}
+
+/*
+ * return -2 iff next is not a variable and not a keyword
+ * return -1 iff next is a keyword and !mustHave
+ * return 1 iff unknown column name or mustHave and keyword
+ * return 0 for success
+ */
+static int read_colname (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ ILLsymboltab * coltab,
+ int mustHave)
+{
+ int rval = 0;
+ int colind = ILL_SYM_NOINDEX;
+
+ rval = EGLPNUM_TYPENAME_ILLread_lp_state_next_var (state);
+ if (mustHave && (rval != 0))
+ {
+ return EGLPNUM_TYPENAME_ILLlp_error (state, "Expecting a column name.\n");
+ }
+ if (rval != 0)
+ {
+ return (rval == -1) ? rval : -2;
+ }
+ if (ILLsymboltab_lookup (coltab, state->field, &colind))
+ {
+ EGLPNUM_TYPENAME_ILLread_lp_state_prev_field (state);
+ return EGLPNUM_TYPENAME_ILLlp_error (state, "\"%s\" is not a column name.\n", state->field);
+ }
+ state->column_index = colind;
+ return 0;
+}
+
+static int read_integer (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+ int rval = 0;
+ ILLsymboltab *coltab = &lp->coltab;
+
+ ILL_FAILfalse (lp->intmarker, "Programming error");
+
+ while ((rval = read_colname (state, coltab, 0)) == 0)
+ {
+ ILL_FAILtrue (state->column_index == ILL_SYM_NOINDEX, "Programming error");
+ lp->intmarker[state->column_index] = 1;
+ }
+CLEANUP:
+ if (rval == -1)
+ { /* last try for a colname gave us a keyword */
+ rval = 0;
+ }
+ else
+ {
+ rval = EGLPNUM_TYPENAME_ILLlp_error (state, "Expecting a column name.");
+ }
+ EGLPNUM_TYPENAME_ILLread_lp_state_next_field (state);
+ EG_RETURN (rval);
+}
+
+static int read_bounds (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+ int rval = 0;
+ int colind, haveBound;
+ char sense;
+ const char *msg;
+ ILLsymboltab *coltab;
+
+ EGLPNUM_TYPENAME_ILLraw_init_bounds (lp);
+ coltab = &lp->coltab;
+
+ while (1)
+ {
+ colind = -1;
+ haveBound = 0;
+ if (EGLPNUM_TYPENAME_ILLread_lp_state_possible_bound_value (state))
+ {
+ /* this must be for a lower bound */
+ EGLPNUM_TYPENAME_ILLtest_lp_state_bound_sense (state);
+ if (state->sense_val != 'L')
+ {
+ rval = EGLPNUM_TYPENAME_ILLlp_error (state, "Expecting \"<=\".\n");
+ break;
+ }
+ rval = read_colname (state, coltab, 1);
+ if (rval != 0)
+ {
+ break;
+ }
+ colind = state->column_index;
+ /* add lower bound value */
+ msg = EGLPNUM_TYPENAME_ILLraw_set_lowerBound (lp, colind, state->bound_val);
+ EGLPNUM_TYPENAME_ILLlp_warn (state, msg);
+ haveBound = 1;
+ }
+ if (colind == -1)
+ {
+ rval = read_colname (state, coltab, 0);
+ colind = state->column_index;
+ if (rval != 0)
+ {
+ if (rval == -1)
+ {
+ rval = 0; /* found a keyword and that's OK */
+ }
+ else if (rval == -2)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlp_error (state, "Expecting a column name.\n");
+ }
+ break;
+ }
+ }
+ ILL_FAILtrue (colind == -1, "must have a valid colname");
+ EGLPNUM_TYPENAME_ILLtest_lp_state_bound_sense (state);
+ if (state->sense_val != ' ')
+ {
+ sense = state->sense_val;
+ if ((sense != 'L') && (sense != 'E'))
+ {
+ rval = EGLPNUM_TYPENAME_ILLlp_error (state, "Expecting \"<=\" or \"=\".\n");
+ break;
+ }
+ if (EGLPNUM_TYPENAME_ILLread_lp_state_possible_bound_value (state))
+ {
+ if (sense == 'E')
+ {
+ msg = EGLPNUM_TYPENAME_ILLraw_set_fixedBound (lp, colind, state->bound_val);
+ }
+ else
+ {
+ msg = EGLPNUM_TYPENAME_ILLraw_set_upperBound (lp, colind, state->bound_val);
+ }
+ EGLPNUM_TYPENAME_ILLlp_warn (state, msg);
+ haveBound = 1;
+ }
+ else
+ {
+ rval = EGLPNUM_TYPENAME_ILLlp_error (state, "Expecting bound value.\n");
+ break;
+ }
+ }
+ else
+ {
+ if (EGLPNUM_TYPENAME_ILLtest_lp_state_next_is (state, "FREE"))
+ {
+ msg = EGLPNUM_TYPENAME_ILLraw_set_unbound (lp, colind);
+ EGLPNUM_TYPENAME_ILLlp_warn (state, msg);
+ haveBound = 1;
+ }
+ else
+ {
+ if (!haveBound)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlp_error (state, "Not a bound expression.\n");
+ break;
+ }
+ }
+ }
+ ILL_IFTRACE ("BOUNDS: %f <= %s <= %f\n", EGLPNUM_TYPENAME_EGlpNumToLf (lp->lower[colind]),
+ EGLPNUM_TYPENAME_ILLraw_colname (lp, colind), EGLPNUM_TYPENAME_EGlpNumToLf (lp->upper[colind]));
+ }
+ EGLPNUM_TYPENAME_ILLread_lp_state_next_field (state);
+CLEANUP:
+ EG_RETURN (rval);
+}
+
+static int add_var (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ EGLPNUM_TYPE coef,
+ int row,
+ int allowNew)
+{
+ char *var = state->field;
+ int rval = 0;
+ int colind;
+
+ if (ILLsymboltab_lookup (&lp->coltab, var, &colind) != 0)
+ {
+ if (!allowNew)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlp_error (state, "Unknown col name \"%s\".\n", var);
+ }
+ CHECKRVALG (rval, CLEANUP);
+ rval = EGLPNUM_TYPENAME_ILLraw_add_col (lp, var, 0 /* not an integer var */ );
+ colind = lp->ncols - 1;
+ CHECKRVALG (rval, CLEANUP);
+ }
+ ILL_IFTRACE ("add_var: \"%s\" coef=%f row=%s\n",
+ var, EGLPNUM_TYPENAME_EGlpNumToLf (coef), EGLPNUM_TYPENAME_ILLraw_rowname (lp, row));
+ rval = EGLPNUM_TYPENAME_ILLraw_add_col_coef (lp, colind, row, coef);
+CLEANUP:
+ EG_RETURN (rval);
+}
diff --git a/qsopt_ex/lp.h b/qsopt_ex/lp.h
new file mode 100644
index 0000000..9e40b91
--- /dev/null
+++ b/qsopt_ex/lp.h
@@ -0,0 +1,74 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCSINFO $Id: lp_EGLPNUM_TYPENAME.h,v 1.2 2003/11/05 16:57:39 meven Exp $ */
+#ifndef EGLPNUM_TYPENAME_LP_H
+#define EGLPNUM_TYPENAME_LP_H
+
+#include "readline_EGLPNUM_TYPENAME.h"
+
+/****************************************************************************/
+/* */
+/* Routines to support Reading and Writing LP Files */
+/* */
+/****************************************************************************/
+/*
+ * -) anything after '\' is comment
+ * -) Problem is optional and comes first
+ * -) Minimize, Maximize, ... comes after Problem
+ * -) variables consist of a-z A-Z 0-9!"#$%(),;.?@_`'{}|~
+ * don't start with a digit or '.'
+ */
+
+#include "lpdata_EGLPNUM_TYPENAME.h"
+#include "rawlp_EGLPNUM_TYPENAME.h"
+#include "read_lp_EGLPNUM_TYPENAME.h"
+#include "write_lp_EGLPNUM_TYPENAME.h"
+
+extern int EGLPNUM_TYPENAME_ILLread_lp (
+ EGLPNUM_TYPENAME_qsline_reader * file,
+ const char *fname,
+ EGLPNUM_TYPENAME_rawlpdata * lp);
+extern int EGLPNUM_TYPENAME_ILLwrite_lp (
+ EGLPNUM_TYPENAME_ILLlpdata * l,
+ EGLPNUM_TYPENAME_qserror_collector * collector);
+
+ /* write using current lp->reporter */
+extern int EGLPNUM_TYPENAME_ILLis_lp_name_char (
+ int c,
+ int pos);
+
+extern int EGLPNUM_TYPENAME_ILLread_constraint_name (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ char **rowname);
+extern int EGLPNUM_TYPENAME_ILLread_one_constraint (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ const char *rowname,
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ int allowNewColsAddRow);
+extern int EGLPNUM_TYPENAME_ILLread_constraint_expr (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ int rowind,
+ int allowNew);
+
+#endif
diff --git a/qsopt_ex/lpdata.c b/qsopt_ex/lpdata.c
new file mode 100644
index 0000000..f0cee50
--- /dev/null
+++ b/qsopt_ex/lpdata.c
@@ -0,0 +1,744 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: lpdata.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+/****************************************************************************/
+/* */
+/* Routines for Manipulating and Writing LPdata */
+/* */
+/* EXPORTED FUNCTIONS */
+/* */
+/* int ILLlpdata_buildrows (EGLPNUM_TYPENAME_ILLlpdata *lp, int **rowbeg, int **rowcnt, */
+/* int **rowind, double **rowval, int include_logicals) */
+/* - include_logicals: if nonzero, then logical variables will be */
+/* included in the row data */
+/* */
+/* */
+/* All _init routines initialize fields of allocated structure to */
+/* appropiate default values */
+/* The _free routines free structures contained in pareameter structure */
+/* but not the parameter itself. */
+/* The _alloc routines check whether given parameter is NULL; they either*/
+/* print an error message or fill structure with default values or the */
+/* given paremeter values. */
+/* */
+/* void EGLPNUM_TYPENAME_ILLlpdata_init (EGLPNUM_TYPENAME_ILLlpdata *lp) */
+/* void EGLPNUM_TYPENAME_ILLlpdata_free (EGLPNUM_TYPENAME_ILLlpdata *lp) */
+/* */
+/* void EGLPNUM_TYPENAME_ILLlp_basis_init (EGLPNUM_TYPENAME_ILLlp_basis *B) */
+/* void EGLPNUM_TYPENAME_ILLlp_basis_free (EGLPNUM_TYPENAME_ILLlp_basis *B) */
+/* int EGLPNUM_TYPENAME_ILLlp_basis_alloc (EGLPNUM_TYPENAME_ILLlp_basis *B, int nstruct, int nrows) */
+/* */
+/* void EGLPNUM_TYPENAME_ILLlp_cache_init (EGLPNUM_TYPENAME_ILLlp_cache *C) */
+/* void EGLPNUM_TYPENAME_ILLlp_cache_free (EGLPNUM_TYPENAME_ILLlp_cache *C) */
+/* int EGLPNUM_TYPENAME_ILLlp_cache_alloc (EGLPNUM_TYPENAME_ILLlp_cache *C, int nstruct, int nrows) */
+/* */
+/* void EGLPNUM_TYPENAME_ILLlp_sinfo_init (EGLPNUM_TYPENAME_ILLlp_sinfo *sinfo) */
+/* void EGLPNUM_TYPENAME_ILLlp_sinfo_free (EGLPNUM_TYPENAME_ILLlp_sinfo *sinfo) */
+/* */
+/* int EGLPNUM_TYPENAME_ILLlp_rows_init(EGLPNUM_TYPENAME_ILLlp_rows *lprows, EGLPNUM_TYPENAME_ILLlpdata *lp, */
+/* int include_logicals) */
+/* */
+/****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "allocrus.h"
+#include "eg_lpnum.h"
+#include "eg_io.h"
+#include "except.h"
+
+#include "lpdata_EGLPNUM_TYPENAME.h"
+#include "qstruct_EGLPNUM_TYPENAME.h"
+#include "qsopt_EGLPNUM_TYPENAME.h"
+#include "lp_EGLPNUM_TYPENAME.h"
+#include "mps_EGLPNUM_TYPENAME.h"
+#include "rawlp_EGLPNUM_TYPENAME.h"
+
+//static int TRACE = 0;
+
+EGLPNUM_TYPE EGLPNUM_TYPENAME_PARAM_IBASIS_RPIVOT;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_PARAM_IBASIS_RTRIANG;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_PARAM_MIN_DNORM;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_PFEAS_TOLER;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_BD_TOLER;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_DFEAS_TOLER;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_PIVOT_TOLER;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_SZERO_TOLER;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_PIVZ_TOLER;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_OBJBND_TOLER;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_DBNDPIV_TOLER;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_DBNDPIV_RATIO;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_ALTPIV_TOLER;
+//EGLPNUM_TYPE DJZERO_TOLER;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_PROGRESS_ZERO; /* 1e-7 */
+EGLPNUM_TYPE EGLPNUM_TYPENAME_PROGRESS_THRESH; /* 1e-5 */
+EGLPNUM_TYPE EGLPNUM_TYPENAME_CB_EPS;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_CB_INF_RATIO;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_CB_PRI_RLIMIT;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_ILL_MAXDOUBLE;
+EGLPNUM_TYPE EGLPNUM_TYPENAME_ILL_MINDOUBLE;
+
+/* ========================================================================= */
+int EGLPNUM_TYPENAME___QSEX_SETUP = 0;
+/* ========================================================================= */
+void EGLPNUM_TYPENAME_ILLstart ( void)
+{
+ if (EGLPNUM_TYPENAME___QSEX_SETUP)
+ return;
+ EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_PARAM_IBASIS_RPIVOT);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_PARAM_IBASIS_RTRIANG);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_PARAM_MIN_DNORM);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_PFEAS_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_BD_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_DFEAS_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_PIVOT_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_SZERO_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_PIVZ_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_OBJBND_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_DBNDPIV_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_DBNDPIV_RATIO);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_ALTPIV_TOLER);
+ //EGLPNUM_TYPENAME_EGlpNumInitVar (DJZERO_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_PROGRESS_ZERO); /* 1e-7 */
+ EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_PROGRESS_THRESH); /* 1e-5 */
+ EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_CB_PRI_RLIMIT);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_CB_INF_RATIO);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_CB_EPS);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+ /* parameters that do depend on the tolerance to zero */
+ EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_PARAM_MIN_DNORM, 4.5036e-9);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_PARAM_MIN_DNORM, EGLPNUM_TYPENAME_epsLpNum);
+ EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_PFEAS_TOLER, 4.5036e9);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_PFEAS_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+ EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_BD_TOLER, 4.5036e8);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_BD_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+ EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_DFEAS_TOLER, 4.5036e9);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_DFEAS_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+ EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_PIVOT_TOLER, 4.5036e5);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_PIVOT_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+ EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_SZERO_TOLER, 4.5036);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_SZERO_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+ EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_PIVZ_TOLER, 4.5036e3);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_PIVZ_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+ EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_OBJBND_TOLER, 4.5036e13);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_OBJBND_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+ EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_ALTPIV_TOLER, 4.5036e7);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_ALTPIV_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+ EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_PROGRESS_ZERO, 4.5036e8);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_PROGRESS_ZERO, EGLPNUM_TYPENAME_epsLpNum);
+ EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_PROGRESS_THRESH, 4.5036e10);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_PROGRESS_THRESH, EGLPNUM_TYPENAME_epsLpNum);
+#if VERBOSE_LEVEL <= DEBUG
+ MESSAGE (VERBOSE_LEVEL, "Setting EGLPNUM_TYPENAME_PARAM_MIN_DNORM to %lg", EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_PARAM_MIN_DNORM));
+ MESSAGE (VERBOSE_LEVEL, "Setting EGLPNUM_TYPENAME_PFEAS_TOLER to %lg", EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_PFEAS_TOLER));
+ MESSAGE (VERBOSE_LEVEL, "Setting EGLPNUM_TYPENAME_BD_TOLER to %lg", EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_BD_TOLER));
+ MESSAGE (VERBOSE_LEVEL, "Setting EGLPNUM_TYPENAME_DFEAS_TOLER to %lg", EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_DFEAS_TOLER));
+ MESSAGE (VERBOSE_LEVEL, "Setting EGLPNUM_TYPENAME_PIVOT_TOLER to %lg", EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_PIVOT_TOLER));
+ MESSAGE (VERBOSE_LEVEL, "Setting EGLPNUM_TYPENAME_SZERO_TOLER to %lg", EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_SZERO_TOLER));
+ MESSAGE (VERBOSE_LEVEL, "Setting EGLPNUM_TYPENAME_PIVZ_TOLER to %lg", EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_PIVZ_TOLER));
+ MESSAGE (VERBOSE_LEVEL, "Setting EGLPNUM_TYPENAME_OBJBND_TOLER to %lg", EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_OBJBND_TOLER));
+ MESSAGE (VERBOSE_LEVEL, "Setting EGLPNUM_TYPENAME_ALTPIV_TOLER to %lg", EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_ALTPIV_TOLER));
+ MESSAGE (VERBOSE_LEVEL, "Setting EGLPNUM_TYPENAME_PROGRESS_ZERO to %lg", EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_PROGRESS_ZERO));
+ MESSAGE (VERBOSE_LEVEL, "Setting EGLPNUM_TYPENAME_PROGRESS_THRESH to %lg", EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_PROGRESS_THRESH));
+#endif
+ /* parameters that do not depend on the tolerance to zero */
+ EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_ILL_MAXDOUBLE, 1e150);
+ EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_ILL_MINDOUBLE, -1e150);
+ EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_PARAM_IBASIS_RPIVOT, 0.98);
+ EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_PARAM_IBASIS_RTRIANG, 0.01);
+ EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_DBNDPIV_TOLER, 1e-3);
+ EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_DBNDPIV_RATIO, 1e-2);
+ //EGLPNUM_TYPENAME_EGlpNumSet (DJZERO_TOLER, 1e-8);
+ EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_CB_EPS, 0.001);
+ EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_CB_INF_RATIO, 10.0);
+ EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_CB_PRI_RLIMIT, 0.25);
+ EGLPNUM_TYPENAME___QSEX_SETUP = 1;
+}
+
+/* ========================================================================= */
+void EGLPNUM_TYPENAME_ILLchange_precision (
+ void)
+{
+ EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_PFEAS_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_BD_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_DFEAS_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_PIVOT_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_SZERO_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_PIVZ_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_OBJBND_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_ALTPIV_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_PARAM_MIN_DNORM);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_PROGRESS_ZERO);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_PROGRESS_THRESH);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_PROGRESS_ZERO);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_PROGRESS_THRESH);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_PFEAS_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_BD_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_DFEAS_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_PIVOT_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_SZERO_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_PIVZ_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_OBJBND_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_ALTPIV_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (EGLPNUM_TYPENAME_PARAM_MIN_DNORM);
+ /* parameters that do depend on the tolerance to zero */
+ EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_PARAM_MIN_DNORM, 4.5036e-9);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_PARAM_MIN_DNORM, EGLPNUM_TYPENAME_epsLpNum);
+ EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_PFEAS_TOLER, 4.5036e9);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_PFEAS_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+ EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_BD_TOLER, 4.5036e8);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_BD_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+ EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_DFEAS_TOLER, 4.5036e9);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_DFEAS_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+ EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_PIVOT_TOLER, 4.5036e5);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_PIVOT_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+ EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_SZERO_TOLER, 4.5036);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_SZERO_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+ EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_PIVZ_TOLER, 4.5036e3);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_PIVZ_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+ EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_OBJBND_TOLER, 4.5036e13);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_OBJBND_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+ EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_ALTPIV_TOLER, 4.5036e7);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_ALTPIV_TOLER, EGLPNUM_TYPENAME_epsLpNum);
+ EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_PROGRESS_ZERO, 4.5036e8);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_PROGRESS_ZERO, EGLPNUM_TYPENAME_epsLpNum);
+ EGLPNUM_TYPENAME_EGlpNumSet (EGLPNUM_TYPENAME_PROGRESS_THRESH, 4.5036e10);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (EGLPNUM_TYPENAME_PROGRESS_THRESH, EGLPNUM_TYPENAME_epsLpNum);
+}
+
+/* ========================================================================= */
+void EGLPNUM_TYPENAME_ILLend ( void)
+{
+ if (!EGLPNUM_TYPENAME___QSEX_SETUP)
+ return;
+ EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_PARAM_IBASIS_RPIVOT);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_PARAM_IBASIS_RTRIANG);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_PARAM_MIN_DNORM);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_PFEAS_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_BD_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_DFEAS_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_PIVOT_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_SZERO_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_PIVZ_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_OBJBND_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_DBNDPIV_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_DBNDPIV_RATIO);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_ALTPIV_TOLER);
+ //EGLPNUM_TYPENAME_EGlpNumClearVar (DJZERO_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_PROGRESS_ZERO); /* 1e-7 */
+ EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_PROGRESS_THRESH); /* 1e-5 */
+ EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_CB_EPS);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_CB_INF_RATIO);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_CB_PRI_RLIMIT);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+ EGLPNUM_TYPENAME___QSEX_SETUP = 0;
+}
+
+EGLPNUM_TYPENAME_QSdata *EGLPNUM_TYPENAME_ILLread (
+ EGLPNUM_TYPENAME_qsline_reader * file,
+ const char *fname,
+ int isMps)
+{
+ int rval = 0;
+ EGLPNUM_TYPENAME_QSdata *p = 0;
+ EGLPNUM_TYPENAME_ILLlpdata *lp;
+ EGLPNUM_TYPENAME_rawlpdata rawlp;
+
+ ILL_FAILfalse (file != NULL, NULL);
+ ILL_FAILfalse (fname != NULL, NULL);
+
+ p = EGLPNUM_TYPENAME_QScreate_prob (fname, QS_MIN);
+ ILL_CHECKnull (p, NULL);
+ ILL_IFFREE (p->qslp->probname, char);
+
+ lp = p->qslp;
+
+ EGLPNUM_TYPENAME_ILLinit_rawlpdata (&rawlp, file->error_collector);
+ EGLPNUM_TYPENAME_ILLlpdata_init (lp);
+
+ if (isMps != 0)
+ {
+ rval = EGLPNUM_TYPENAME_ILLread_mps (file, fname, &rawlp);
+ }
+ else
+ {
+ rval = EGLPNUM_TYPENAME_ILLread_lp (file, fname, &rawlp);
+ }
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLrawlpdata_to_lpdata (&rawlp, lp);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+ EGLPNUM_TYPENAME_ILLfree_rawlpdata (&rawlp);
+ if (rval != 0)
+ {
+ EGLPNUM_TYPENAME_QSfree_prob (p);
+ p = 0;
+ }
+ return p;
+}
+
+static int EGLPNUM_TYPENAME_ILLlpdata_log(
+ void *dest, const char *s)
+{
+ if (s != NULL) {
+ QSlog("%s", s);
+ }
+ return 0;
+}
+
+void EGLPNUM_TYPENAME_ILLlpdata_init (
+ EGLPNUM_TYPENAME_ILLlpdata * lp)
+{
+ if (lp)
+ {
+ lp->nrows = 0;
+ lp->ncols = 0;
+ lp->nstruct = 0;
+ lp->nzcount = 0;
+ lp->rowsize = 0;
+ lp->colsize = 0;
+ lp->structsize = 0;
+ lp->objsense = EGLPNUM_TYPENAME_ILL_MIN;
+ lp->sense = 0;
+ lp->obj = 0;
+ lp->rhs = 0;
+ lp->rangeval = 0;
+ lp->lower = 0;
+ lp->upper = 0;
+
+ EGLPNUM_TYPENAME_ILLmatrix_init (&lp->A);
+ EGLPNUM_TYPENAME_ILLmatrix_init (&lp->sos);
+ lp->rA = 0;
+ lp->is_sos_mem = NULL;
+ lp->refrowname = NULL;
+ lp->refind = -1;
+
+ lp->colnames = 0;
+ ILLsymboltab_init (&lp->coltab);
+ lp->rownames = 0;
+ ILLsymboltab_init (&lp->rowtab);
+ lp->objname = 0;
+
+ lp->probname = 0;
+ lp->intmarker = 0;
+ lp->structmap = 0;
+ lp->rowmap = 0;
+ lp->basis = 0;
+ /*lp->presolve = 0; */
+ lp->sinfo = 0;
+
+ ILLstring_reporter_init(
+ &lp->reporter, EGLPNUM_TYPENAME_ILLlpdata_log, NULL);
+ }
+}
+
+void EGLPNUM_TYPENAME_ILLlpdata_free (
+ EGLPNUM_TYPENAME_ILLlpdata * lp)
+{
+ int i;
+
+ if (lp)
+ {
+ ILL_IFFREE (lp->sense, char);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->obj);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->rhs);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->rangeval);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->lower);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->upper);
+ EGLPNUM_TYPENAME_ILLmatrix_free (&lp->A);
+ if (lp->rA)
+ {
+ EGLPNUM_TYPENAME_ILLlp_rows_clear (lp->rA);
+ ILL_IFFREE (lp->rA, EGLPNUM_TYPENAME_ILLlp_rows);
+ }
+ ILL_IFFREE (lp->is_sos_mem, int);
+ ILL_IFFREE (lp->refrowname, char);
+
+ EGLPNUM_TYPENAME_ILLmatrix_free (&lp->sos);
+ if (lp->colnames)
+ {
+ for (i = 0; i < lp->nstruct; i++)
+ {
+ ILL_IFFREE (lp->colnames[i], char);
+ }
+ ILL_IFFREE (lp->colnames, char *);
+ }
+ ILLsymboltab_free (&lp->coltab);
+ if (lp->rownames)
+ {
+ for (i = 0; i < lp->nrows; i++)
+ {
+ ILL_IFFREE (lp->rownames[i], char);
+ }
+ ILL_IFFREE (lp->rownames, char *);
+ }
+ ILLsymboltab_free (&lp->rowtab);
+ ILL_IFFREE (lp->objname, char);
+ ILL_IFFREE (lp->probname, char);
+ ILL_IFFREE (lp->intmarker, char);
+ ILL_IFFREE (lp->structmap, int);
+ ILL_IFFREE (lp->rowmap, int);
+
+ if (lp->sinfo)
+ {
+ EGLPNUM_TYPENAME_ILLlp_sinfo_free (lp->sinfo);
+ ILL_IFFREE (lp->sinfo, EGLPNUM_TYPENAME_ILLlp_sinfo);
+ }
+ EGLPNUM_TYPENAME_ILLlpdata_init (lp);
+ }
+}
+
+void EGLPNUM_TYPENAME_ILLlp_basis_init (
+ EGLPNUM_TYPENAME_ILLlp_basis * B)
+{
+ if (B)
+ {
+ B->cstat = 0;
+ B->rstat = 0;
+ B->rownorms = 0;
+ B->colnorms = 0;
+ B->nstruct = 0;
+ B->nrows = 0;
+ }
+}
+
+void EGLPNUM_TYPENAME_ILLlp_basis_free (
+ EGLPNUM_TYPENAME_ILLlp_basis * B)
+{
+ if (B)
+ {
+ ILL_IFFREE (B->cstat, char);
+ ILL_IFFREE (B->rstat, char);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (B->rownorms);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (B->colnorms);
+ B->nstruct = 0;
+ B->nrows = 0;
+ }
+}
+
+int EGLPNUM_TYPENAME_ILLlp_basis_alloc (
+ EGLPNUM_TYPENAME_ILLlp_basis * B,
+ int nstruct,
+ int nrows)
+{
+ int rval = 0;
+
+ ILL_FAILtrue (B == NULL, "EGLPNUM_TYPENAME_ILLlp_basis_alloc called without a basis");
+
+ B->nstruct = nstruct;
+ B->nrows = nrows;
+
+ if (nstruct > 0)
+ {
+ ILL_SAFE_MALLOC (B->cstat, nstruct, char);
+ }
+
+ if (nrows > 0)
+ {
+ ILL_SAFE_MALLOC (B->rstat, nrows, char);
+ }
+
+CLEANUP:
+
+ if (rval)
+ {
+ EGLPNUM_TYPENAME_ILLlp_basis_free (B);
+ }
+
+ EG_RETURN (rval);
+}
+
+void EGLPNUM_TYPENAME_ILLlp_cache_init (
+ EGLPNUM_TYPENAME_ILLlp_cache * C)
+{
+ if (C)
+ {
+ C->x = 0;
+ C->rc = 0;
+ C->pi = 0;
+ C->slack = 0;
+ C->nstruct = 0;
+ C->nrows = 0;
+ C->status = 0;
+ EGLPNUM_TYPENAME_EGlpNumZero (C->val);
+ }
+}
+
+void EGLPNUM_TYPENAME_ILLlp_cache_free (
+ EGLPNUM_TYPENAME_ILLlp_cache * C)
+{
+ if (C)
+ {
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (C->x);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (C->rc);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (C->pi);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (C->slack);
+ C->nstruct = 0;
+ C->nrows = 0;
+ C->status = 0;
+ }
+}
+
+int EGLPNUM_TYPENAME_ILLlp_cache_alloc (
+ EGLPNUM_TYPENAME_ILLlp_cache * C,
+ int nstruct,
+ int nrows)
+{
+ int rval = 0;
+
+ ILL_FAILtrue (C == NULL, "EGLPNUM_TYPENAME_ILLlp_cache_alloc called without a cache");
+
+ C->nstruct = nstruct;
+ C->nrows = nrows;
+
+ if (nstruct > 0)
+ {
+ C->x = EGLPNUM_TYPENAME_EGlpNumAllocArray (nstruct);
+ C->rc = EGLPNUM_TYPENAME_EGlpNumAllocArray (nstruct);
+ }
+
+ if (nrows > 0)
+ {
+ C->pi = EGLPNUM_TYPENAME_EGlpNumAllocArray (nrows);
+ C->slack = EGLPNUM_TYPENAME_EGlpNumAllocArray (nrows);
+ }
+
+CLEANUP:
+
+ if (rval)
+ {
+ EGLPNUM_TYPENAME_ILLlp_cache_free (C);
+ }
+
+ EG_RETURN (rval);
+}
+
+
+int EGLPNUM_TYPENAME_ILLlp_rows_init (
+ EGLPNUM_TYPENAME_ILLlp_rows * lprows,
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ int include_logicals)
+{
+ int rval = 0;
+ int i, k, st;
+ int *beg, *cnt, *ind;
+ EGLPNUM_TYPE *val;
+ EGLPNUM_TYPENAME_ILLmatrix *A;
+ char *hit = 0;
+ int *inv_structmap = 0;
+
+ /* If logicals are not included, then the columns are ordered as in */
+ /* lp->structmap. Otherwise, the columns are ordered as in the */
+ /* matrix structure. */
+
+ if (lprows != NULL)
+ {
+ lprows->rowbeg = 0;
+ lprows->rowcnt = 0;
+ lprows->rowind = 0;
+ lprows->rowval = 0;
+ }
+
+ ILL_FAILfalse ((lp != NULL) && (lprows != NULL),
+ "called with a NULL pointer");
+
+ A = &lp->A;
+
+ if (lp->nrows > 0)
+ {
+ if (include_logicals == 0)
+ {
+ ILL_FAILtrue (lp->rowmap == NULL, "Programming error.");
+ ILL_SAFE_MALLOC (hit, lp->ncols, char);
+
+ for (i = 0; i < lp->ncols; i++)
+ {
+ hit[i] = 0;
+ }
+ for (i = 0; i < lp->nrows; i++)
+ {
+ hit[lp->rowmap[i]] = 1;
+ }
+
+ ILL_SAFE_MALLOC (inv_structmap, lp->ncols, int);
+
+ for (i = 0; i < lp->nstruct; i++)
+ {
+ inv_structmap[lp->structmap[i]] = i;
+ }
+ }
+
+ ILL_SAFE_MALLOC (lprows->rowbeg, lp->nrows, int);
+ ILL_SAFE_MALLOC (lprows->rowcnt, lp->nrows, int);
+
+ if (((include_logicals != 0) && lp->nzcount > 0) ||
+ ((include_logicals == 0) && lp->nzcount > lp->nrows))
+ {
+ if (include_logicals != 0)
+ {
+ ILL_SAFE_MALLOC (lprows->rowind, lp->nzcount, int);
+
+ lprows->rowval = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nzcount);
+ }
+ else
+ {
+ ILL_SAFE_MALLOC (lprows->rowind, lp->nzcount - lp->nrows, int);
+
+ lprows->rowval = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nzcount - lp->nrows);
+ }
+ }
+
+ beg = lprows->rowbeg;
+ cnt = lprows->rowcnt;
+ ind = lprows->rowind;
+ val = lprows->rowval;
+
+ for (i = 0; i < lp->nrows; i++)
+ {
+ cnt[i] = 0;
+ }
+
+ for (i = 0; i < lp->ncols; i++)
+ {
+ if ((include_logicals != 0) || hit[i] == 0)
+ {
+ k = A->matbeg[i];
+ st = k + A->matcnt[i];
+ for (; k < st; k++)
+ {
+ cnt[A->matind[k]]++;
+ }
+ }
+ }
+
+ for (i = 0, k = 0; i < lp->nrows; i++)
+ {
+ beg[i] = k;
+ k += cnt[i];
+ }
+
+ for (i = 0; i < lp->ncols; i++)
+ {
+ if ((include_logicals != 0) || hit[i] == 0)
+ {
+ k = A->matbeg[i];
+ st = k + A->matcnt[i];
+ for (; k < st; k++)
+ {
+ if (include_logicals != 0)
+ {
+ ind[beg[A->matind[k]]] = i;
+ }
+ else
+ {
+ ind[beg[A->matind[k]]] = inv_structmap[i];
+ }
+ EGLPNUM_TYPENAME_EGlpNumCopy (val[beg[A->matind[k]]], A->matval[k]);
+ beg[A->matind[k]]++;
+ }
+ }
+ }
+
+ for (i = 0, k = 0; i < lp->nrows; i++)
+ {
+ beg[i] = k;
+ k += cnt[i];
+ }
+ }
+CLEANUP:
+
+ if (rval)
+ {
+ EGLPNUM_TYPENAME_ILLlp_rows_clear (lprows);
+ }
+ ILL_IFFREE (hit, char);
+ ILL_IFFREE (inv_structmap, int);
+
+ EG_RETURN (rval);
+}
+
+void EGLPNUM_TYPENAME_ILLlp_rows_clear (
+ EGLPNUM_TYPENAME_ILLlp_rows * lprows)
+{
+ if (lprows != NULL)
+ {
+ ILL_IFFREE (lprows->rowbeg, int);
+ ILL_IFFREE (lprows->rowcnt, int);
+ ILL_IFFREE (lprows->rowind, int);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (lprows->rowval);
+ }
+}
+
+static int wr_line (
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ const char *format,
+ va_list argptr)
+{
+ char buffer[ILL_namebufsize];
+ int rval = 0;
+
+ rval = vsprintf (buffer, format, argptr);
+ if (rval > 0)
+ {
+ /* Bico -- OPTERON DEBUGGING 051005 */
+ /* Replaced ILLstring_report by the explicit call to */
+ /* fprintf. */
+ /*rval = fprintf (lp->reporter.dest, buffer);
+ if (rval < 0) rval = 1;
+ else rval = 0;
+ */
+ /* daespino -- BACK to ILLstring_report to support compresed files 090909
+ * */
+ rval = ILLstring_report(buffer, &lp->reporter);
+ }
+ return rval;
+}
+
+int EGLPNUM_TYPENAME_ILLprint_report (
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ const char *format,
+ ...)
+{
+ va_list marker;
+ int rval = 0;
+
+ va_start (marker, format); /* ANSI style */
+ rval = wr_line (lp, format, marker);
+ va_end (marker); /* Reset variable arguments. */
+ return rval;
+}
diff --git a/qsopt_ex/lpdata.h b/qsopt_ex/lpdata.h
new file mode 100644
index 0000000..452df5d
--- /dev/null
+++ b/qsopt_ex/lpdata.h
@@ -0,0 +1,303 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCSINFO $Id: lpdata_EGLPNUM_TYPENAME.h,v 1.4 2003/11/05 17:00:56 meven Exp $ */
+#ifndef EGLPNUM_TYPENAME_ILL_LPDATA_H
+#define EGLPNUM_TYPENAME_ILL_LPDATA_H
+
+#include "eg_lpnum.h"
+#include "reporter.h"
+#include "symtab.h"
+
+#include "qstruct_EGLPNUM_TYPENAME.h"
+#include "readline_EGLPNUM_TYPENAME.h"
+#include "format_EGLPNUM_TYPENAME.h"
+#include "dstruct_EGLPNUM_TYPENAME.h"
+
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_ILL_MAXDOUBLE; /* 1e150 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_ILL_MINDOUBLE; /* -1e150 */
+
+#define EGLPNUM_TYPENAME_ILL_MAXINT (2147483647) /* this is equal to 2^31-1 */
+#define EGLPNUM_TYPENAME_ILL_MIN (1) /* Must be same as QS_MIN */
+#define EGLPNUM_TYPENAME_ILL_MAX (-1) /* Must be same as QS_MAX */
+
+/* Setting Alg in Presolve */
+
+#define EGLPNUM_TYPENAME_ILL_PRE_SCALE 1
+#define EGLPNUM_TYPENAME_ILL_PRE_FIXED 2
+#define EGLPNUM_TYPENAME_ILL_PRE_SINGLE_ROW 4
+#define EGLPNUM_TYPENAME_ILL_PRE_FORCING 8
+#define EGLPNUM_TYPENAME_ILL_PRE_SINGLE_COL 16
+#define EGLPNUM_TYPENAME_ILL_PRE_DUPLICATE_ROW 32
+#define EGLPNUM_TYPENAME_ILL_PRE_DUPLICATE_COL 64
+#define EGLPNUM_TYPENAME_ILL_PRE_EMPTY_COL 128
+#define EGLPNUM_TYPENAME_ILL_PRE_ALL (EGLPNUM_TYPENAME_ILL_PRE_SCALE | EGLPNUM_TYPENAME_ILL_PRE_FIXED | EGLPNUM_TYPENAME_ILL_PRE_SINGLE_ROW \
+ EGLPNUM_TYPENAME_ILL_PRE_FORCING | EGLPNUM_TYPENAME_ILL_PRE_SINGLE_COL | EGLPNUM_TYPENAME_ILL_PRE_DUPLICATE_ROW \
+ EGLPNUM_TYPENAME_ILL_PRE_DUPLICATE_COL | EGLPNUM_TYPENAME_ILL_PRE_EMPTY_COL)
+#define EGLPNUM_TYPENAME_ILL_PRE_SIMPLE (EGLPNUM_TYPENAME_ILL_PRE_FIXED | EGLPNUM_TYPENAME_ILL_PRE_EMPTY_COL)
+
+typedef struct EGLPNUM_TYPENAME_ILLlpdata
+{ /* Complete LP data filled in by mpsread. */
+ int nrows;
+ int ncols;
+ int nstruct; /* Not including logicals. */
+ int nzcount;
+ int rowsize; /* Length of row arrays. */
+ int colsize; /* Length of col arrays. */
+ int structsize; /* Length of intmarker, structmap, */
+ /* colnames */
+ int objsense;
+ char *sense; /* Original sense, not after logicals. */
+ EGLPNUM_TYPE *obj;
+ EGLPNUM_TYPE *rhs;
+ EGLPNUM_TYPE *rangeval;
+ EGLPNUM_TYPE *lower;
+ EGLPNUM_TYPE *upper;
+ EGLPNUM_TYPENAME_ILLmatrix A; /* The coef matrix. */
+ struct EGLPNUM_TYPENAME_ILLlp_rows *rA; /* Coef matrix in row form. */
+
+ char **rownames;
+ ILLsymboltab rowtab; /* contains rownames in no particular order */
+ char *objname; /* if colname is not NULL it is entered into
+ * the rowtab, see reader fcts in lp.c, mps.c*/
+
+ char **colnames; /* columns of struct variables */
+ ILLsymboltab coltab; /* contains colnames in no particular order */
+
+ char *probname;
+ char *intmarker;
+ int *structmap; /* Indices of structural variables */
+ int *rowmap; /* Indices of logical and range variables */
+ struct EGLPNUM_TYPENAME_ILLlp_basis *basis;
+ struct EGLPNUM_TYPENAME_ILLlp_predata *presolve;
+ struct EGLPNUM_TYPENAME_ILLlp_sinfo *sinfo;
+
+ /**************************************************************************/
+ /* these fields are currently only set by mps.c reader fcts */
+ /**************************************************************************/
+ EGLPNUM_TYPENAME_ILLmatrix sos; /* columns are the sets, rows are the
+ * problem's structural variables
+ * coefficients are the weights */
+
+ char *sos_type; /* type of each set */
+ int *is_sos_mem; /* for each structural variable contains
+ * -1 == not a set member
+ * i == member of sos set i
+ * where 0 <= i < sos.matcols */
+ char *refrowname; /* name of reference row */
+ int refind; /* index of reference row
+ * -1 if refrow was a free row
+ * and weights are found only in the
+ * sos matrix
+ * index >=0 if refrow is also a lp-row */
+
+ /**************************************************************************
+ * EGLPNUM_TYPENAME_QSset_reporter initializes reporter
+ **************************************************************************/
+ qsstring_reporter reporter; /* used from within ILL fcts
+ * to report feedback */
+}
+EGLPNUM_TYPENAME_ILLlpdata;
+
+typedef struct EGLPNUM_TYPENAME_ILLlp_basis
+{
+ int nstruct;
+ int nrows;
+ int rownorms_size;
+ int colnorms_size;
+ char *cstat;
+ char *rstat;
+ EGLPNUM_TYPE *rownorms;
+ EGLPNUM_TYPE *colnorms;
+}
+EGLPNUM_TYPENAME_ILLlp_basis;
+
+typedef struct EGLPNUM_TYPENAME_ILLlp_cache
+{
+ int nstruct;
+ int nrows;
+ int status;
+ EGLPNUM_TYPE val;
+ EGLPNUM_TYPE *x;
+ EGLPNUM_TYPE *pi;
+ EGLPNUM_TYPE *rc;
+ EGLPNUM_TYPE *slack;
+}
+EGLPNUM_TYPENAME_ILLlp_cache;
+
+typedef struct EGLPNUM_TYPENAME_ILLlp_sinfo
+{ /* LP info returned by presolve */
+ int ncols;
+ int nrows;
+ int nzcount;
+ int rowsize;
+ int colsize;
+ int objsense;
+
+ EGLPNUM_TYPE *obj;
+ EGLPNUM_TYPE *rhs;
+ EGLPNUM_TYPE *lower;
+ EGLPNUM_TYPE *upper;
+
+ EGLPNUM_TYPENAME_ILLmatrix A;
+
+ char **colnames; /* Just for debugging - not updated */
+}
+EGLPNUM_TYPENAME_ILLlp_sinfo;
+
+typedef struct EGLPNUM_TYPENAME_ILLlp_preline
+{
+ EGLPNUM_TYPE rhs;
+ EGLPNUM_TYPE obj;
+ EGLPNUM_TYPE lower;
+ EGLPNUM_TYPE upper;
+ int count;
+ int *ind;
+ int row_or_col; /* 0 is row, 1 is col */
+ EGLPNUM_TYPE *val;
+}
+EGLPNUM_TYPENAME_ILLlp_preline;
+
+typedef struct EGLPNUM_TYPENAME_ILLlp_preop
+{
+ int ptype;
+ int rowindex;
+ int colindex;
+ EGLPNUM_TYPENAME_ILLlp_preline line;
+}
+EGLPNUM_TYPENAME_ILLlp_preop;
+
+typedef struct EGLPNUM_TYPENAME_ILLlp_predata
+{ /* Data needed in un-presolve. */
+ int opcount;
+ int opsize;
+ EGLPNUM_TYPENAME_ILLlp_preop *oplist;
+ int r_nrows;
+ int r_ncols;
+ int *colmap;
+ int *rowmap;
+ EGLPNUM_TYPE *rowscale;
+ EGLPNUM_TYPE *colscale;
+ EGLPNUM_TYPE *colfixval;
+ EGLPNUM_TYPE *rowfixval;
+}
+EGLPNUM_TYPENAME_ILLlp_predata;
+
+typedef struct EGLPNUM_TYPENAME_ILLlp_rows
+{
+ int *rowbeg;
+ int *rowcnt;
+ int *rowind;
+ EGLPNUM_TYPE *rowval;
+}
+EGLPNUM_TYPENAME_ILLlp_rows;
+
+
+/****************************************************************************/
+/* */
+/* lpdata.c */
+/* */
+/****************************************************************************/
+
+struct EGLPNUM_TYPENAME_qsdata *EGLPNUM_TYPENAME_ILLread (
+ EGLPNUM_TYPENAME_qsline_reader * file,
+ const char *fname,
+ int isMps);
+void EGLPNUM_TYPENAME_ILLstart (
+ void); /**< initialize EGLPNUM_TYPENAME_ILL_MAXDOUBLE and other
+
+ constants, this funtion should be callef AFTER
+ EGlpNumStart() */
+void EGLPNUM_TYPENAME_ILLend (
+ void); /**< free any internal data asociated with variable
+
+ precision numbers */
+void EGLPNUM_TYPENAME_ILLchange_precision (
+ void); /**< This function re-compute the internal
+
+ variables precision to the (previously
+ set) EGLPNUM_PRECISION value (done with
+ EGlpNumSetPrecision) */
+void EGLPNUM_TYPENAME_ILLlpdata_init (
+ EGLPNUM_TYPENAME_ILLlpdata * lp);
+void EGLPNUM_TYPENAME_ILLlpdata_free (
+ EGLPNUM_TYPENAME_ILLlpdata * lp);
+void EGLPNUM_TYPENAME_ILLlp_basis_init (
+ EGLPNUM_TYPENAME_ILLlp_basis * B);
+void EGLPNUM_TYPENAME_ILLlp_basis_free (
+ EGLPNUM_TYPENAME_ILLlp_basis * B);
+void EGLPNUM_TYPENAME_ILLlp_cache_init (
+ EGLPNUM_TYPENAME_ILLlp_cache * C);
+void EGLPNUM_TYPENAME_ILLlp_cache_free (
+ EGLPNUM_TYPENAME_ILLlp_cache * C);
+int EGLPNUM_TYPENAME_ILLlp_basis_alloc (
+ EGLPNUM_TYPENAME_ILLlp_basis * B,
+ int ncols,
+ int nrows);
+int EGLPNUM_TYPENAME_ILLlp_cache_alloc (
+ EGLPNUM_TYPENAME_ILLlp_cache * C,
+ int ncols,
+ int nrows);
+
+int EGLPNUM_TYPENAME_ILLlp_rows_init (
+ EGLPNUM_TYPENAME_ILLlp_rows * lp_rows,
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ int include_logicals);
+void EGLPNUM_TYPENAME_ILLlp_rows_clear (
+ EGLPNUM_TYPENAME_ILLlp_rows * lp_rows);
+int EGLPNUM_TYPENAME_ILLprint_report (
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ const char *format,
+ ...);
+
+ /* print to lp->reporter */
+
+/****************************************************************************/
+/* */
+/* presolve.c */
+/* */
+/****************************************************************************/
+
+void EGLPNUM_TYPENAME_ILLlp_sinfo_init (
+ EGLPNUM_TYPENAME_ILLlp_sinfo * sinfo),
+ EGLPNUM_TYPENAME_ILLlp_sinfo_free (
+ EGLPNUM_TYPENAME_ILLlp_sinfo * sinfo),
+ EGLPNUM_TYPENAME_ILLlp_predata_init (
+ EGLPNUM_TYPENAME_ILLlp_predata * pre),
+ EGLPNUM_TYPENAME_ILLlp_predata_free (
+ EGLPNUM_TYPENAME_ILLlp_predata * pre);
+
+int EGLPNUM_TYPENAME_ILLlp_add_logicals (
+ EGLPNUM_TYPENAME_ILLlpdata * lp),
+ EGLPNUM_TYPENAME_ILLlp_scale (
+ EGLPNUM_TYPENAME_ILLlpdata * lp),
+ EGLPNUM_TYPENAME_ILLlp_presolve (
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ int pre_types);
+
+/* ========================================================================= */
+/* if non-zero, then internal data has been initialized, and there is some
+ * memory allocated, if zero, no internal memory has been allocated
+ * (or it has been freed) */
+extern int EGLPNUM_TYPENAME___QSEX_SETUP;
+
+#endif /* __ILL_LPDATA_H */
diff --git a/qsopt_ex/lpdefs.h b/qsopt_ex/lpdefs.h
new file mode 100644
index 0000000..decc400
--- /dev/null
+++ b/qsopt_ex/lpdefs.h
@@ -0,0 +1,330 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCSINFO $Id: lpdefs_EGLPNUM_TYPENAME.h,v 1.3 2003/11/05 16:57:39 meven Exp $ */
+#ifndef EGLPNUM_TYPENAME___QS_LPDEFS_H
+#define EGLPNUM_TYPENAME___QS_LPDEFS_H
+
+#include "urandom.h"
+
+#include "qsopt_EGLPNUM_TYPENAME.h"
+#include "lpdata_EGLPNUM_TYPENAME.h"
+#include "factor_EGLPNUM_TYPENAME.h"
+
+/* infinity and negative infinity */
+#define EGLPNUM_TYPENAME_INFTY EGLPNUM_TYPENAME_ILL_MAXDOUBLE
+#define EGLPNUM_TYPENAME_NINFTY EGLPNUM_TYPENAME_ILL_MINDOUBLE
+
+#include "basicdefs.h"
+/* tolerances, these are initialized in EGLPNUM_TYPENAME_ILLstart, file lpdata.c */
+/* these three constants are defined in lpdata.c */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_PARAM_IBASIS_RPIVOT; /* 0.98 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_PARAM_IBASIS_RTRIANG;/* 0.01 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_PARAM_MIN_DNORM; /* 1e-24 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_PFEAS_TOLER; /* 1e-6 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_BD_TOLER; /* 1e-7 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_DFEAS_TOLER; /* 1e-6 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_PIVOT_TOLER; /* 1e-10 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_SZERO_TOLER; /* 1e-15 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_PIVZ_TOLER; /* 1e-12 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_OBJBND_TOLER; /* 1e-2 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_DBNDPIV_TOLER; /* 1e-3 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_DBNDPIV_RATIO; /* 1e-2 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_ALTPIV_TOLER; /* 1e-8 */
+//extern EGLPNUM_TYPE DJZERO_TOLER;/* 1e-8 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_PROGRESS_ZERO; /* 1e-7 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_PROGRESS_THRESH; /* 1e-5 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_CB_EPS; /* 0.001 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_CB_INF_RATIO; /* 10.0 */
+extern EGLPNUM_TYPE EGLPNUM_TYPENAME_CB_PRI_RLIMIT; /* 0.25 */
+
+/* structure for statistics */
+typedef struct
+{
+ int ynz_cnt; /* nz in entering columns */
+ int num_y;
+ EGLPNUM_TYPE y_ravg; /* weighted avg. of current & prior y */
+ int znz_cnt; /* nz in ith row of B^{-1}, ie z_i */
+ int num_z;
+ EGLPNUM_TYPE z_ravg; /* weighted avg. of current & prior z */
+ int zanz_cnt; /* nz in z^TA */
+ int num_za;
+ EGLPNUM_TYPE za_ravg; /* weighted avg. of current & prior za */
+ int pnorm_cnt; /* nz in columns for primal norms */
+ int dnorm_cnt; /* nz in rows for dual norms */
+ int pinz_cnt; /* nz in phase II pi (solve) */
+ int num_pi; /* # of pi solves */
+ int pi1nz_cnt; /* nz in phase I pi (solve) */
+ int num_pi1; /* # of phase I pi solves */
+ int upnz_cnt; /* nz in ftran update vector */
+ int num_up; /* # of ftran_updates */
+ int pupv_cnt; /* nz in primal steep updates */
+ int dupv_cnt; /* nz in dual steep updates */
+
+ int start_slacks; /* # slacks in beginning */
+ int final_slacks; /* # slacks in the end */
+ int start_art; /* # arts in beginning */
+ int final_art; /* # arts in the end */
+
+ int pI_iter; /* primal phase I iterations */
+ int pII_iter;
+ int dI_iter; /* dual phase I iterations */
+ int dII_iter;
+ int tot_iter;
+
+ int pivpI[10]; /* sizes of pivots */
+ int pivpII[10];
+ int pivdI[10];
+ int pivdII[10];
+}
+EGLPNUM_TYPENAME_count_struct;
+
+/* structure for tolerances */
+typedef struct
+{
+ EGLPNUM_TYPE pfeas_tol;
+ EGLPNUM_TYPE dfeas_tol;
+ EGLPNUM_TYPE pivot_tol;
+ EGLPNUM_TYPE szero_tol;
+ EGLPNUM_TYPE ip_tol; /* inner primal & dual feas toler */
+ EGLPNUM_TYPE id_tol;
+}
+EGLPNUM_TYPENAME_tol_struct;
+
+/* bound information */
+typedef struct EGLPNUM_TYPENAME_bndinfo
+{
+ EGLPNUM_TYPE pbound;
+ EGLPNUM_TYPE cbound;
+ int btype;
+ int varnum;
+ struct EGLPNUM_TYPENAME_bndinfo *next;
+}
+EGLPNUM_TYPENAME_bndinfo;
+
+/* bound information */
+typedef struct EGLPNUM_TYPENAME_coefinfo
+{
+ EGLPNUM_TYPE pcoef;
+ EGLPNUM_TYPE ccoef;
+ int varnum;
+ struct EGLPNUM_TYPENAME_coefinfo *next;
+}
+EGLPNUM_TYPENAME_coefinfo;
+
+/* feasibility info */
+typedef struct EGLPNUM_TYPENAME_feas_info
+{
+ int pstatus;
+ int dstatus;
+ EGLPNUM_TYPE totinfeas;
+}
+EGLPNUM_TYPENAME_feas_info;
+
+typedef struct EGLPNUM_TYPENAME_lp_status_info
+{
+ char optimal;
+ char primal_feasible;
+ char primal_infeasible;
+ char primal_unbounded;
+ char dual_feasible;
+ char dual_infeasible;
+ char dual_unbounded;
+ char padd;
+}
+EGLPNUM_TYPENAME_lp_status_info;
+
+typedef struct EGLPNUM_TYPENAME_pI_uinfo
+{
+ int tctr;
+ int i;
+ int *perm;
+ int *ix;
+ int fs;
+ EGLPNUM_TYPE piv;
+ EGLPNUM_TYPE *t;
+ EGLPNUM_TYPE dty;
+ EGLPNUM_TYPE c_obj;
+ EGLPNUM_TYPE tz;
+}
+EGLPNUM_TYPENAME_pI_uinfo;
+
+extern void EGLPNUM_TYPENAME_ILLlp_status_info_init (
+ EGLPNUM_TYPENAME_lp_status_info * ls);
+
+/* structure for local lp information
+ * contains lp obj values - status - dimensions - input data -
+ * solution vecs - basis info - update vecs - work vecs - bound changes -
+ * tolerances - time info - statistics
+ */
+typedef struct EGLPNUM_TYPENAME_lpinfo
+{
+
+ EGLPNUM_TYPE objval; /* obj info */
+ EGLPNUM_TYPE pobjval; /* intermediate status info */
+ EGLPNUM_TYPE dobjval;
+ EGLPNUM_TYPE pinfeas;
+ EGLPNUM_TYPE dinfeas;
+ EGLPNUM_TYPE objbound;
+ EGLPNUM_TYPENAME_lp_status_info probstat; /* final status */
+ EGLPNUM_TYPENAME_lp_status_info basisstat; /* final status */
+ int nrows; /* input info follows; given in col format */
+ int ncols;
+ int *matcnt;
+ int *matbeg;
+ int *matind;
+ EGLPNUM_TYPE *matval;
+ int matfree;
+ int matsize;
+ EGLPNUM_TYPE *bz;
+ EGLPNUM_TYPE *lz;
+ EGLPNUM_TYPE *uz;
+ EGLPNUM_TYPE *cz;
+ int localrows; /* set to 1 if these are created locally */
+ int *rowcnt; /* row info follows, copy of col info */
+ int *rowbeg;
+ int *rowind;
+ EGLPNUM_TYPE *rowval;
+
+ EGLPNUM_TYPE *xbz; /* output info x, pi, reduced cost */
+ EGLPNUM_TYPE *piz;
+ EGLPNUM_TYPE *dz;
+ EGLPNUM_TYPE *pIxbz; /* output info (phase I) x, pi, reduced cost */
+ EGLPNUM_TYPE *pIpiz;
+ EGLPNUM_TYPE *pIdz;
+
+ int final_phase; /* final phase, inf & unboundedness info */
+ int infub_ix;
+
+ int basisid; /* basis and variable info follows */
+ int nnbasic;
+ int *baz;
+ int *nbaz;
+ int *vstat;
+ int *vindex;
+ int fbasisid;
+ EGLPNUM_TYPENAME_factor_work *f;
+ int *vtype; /* internal var info */
+ char *vclass; /* structural or logical */
+
+ EGLPNUM_TYPENAME_svector zz; /* local EGLPNUM_TYPENAME_ILLfactor_update vectors z, yj, za */
+ EGLPNUM_TYPENAME_svector yjz;
+ EGLPNUM_TYPENAME_svector zA;
+ EGLPNUM_TYPENAME_svector work; /* local work vector */
+ EGLPNUM_TYPENAME_svector srhs; /* local vectors for lin. eq. solves */
+ EGLPNUM_TYPENAME_svector ssoln;
+ int *iwork; /* local work vector */
+ EGLPNUM_TYPENAME_pI_uinfo upd; /* phase I update info */
+ int *bfeas; /* primal and dual infeasibility info */
+ int *dfeas;
+
+ EGLPNUM_TYPENAME_tol_struct *tol; /* tolerances */
+ EGLPNUM_TYPENAME_count_struct *cnts; /* counts */
+ int nbchange; /* # bound shifts */
+ int ncchange; /* # obj coef shifts */
+ EGLPNUM_TYPENAME_bndinfo *bchanges; /* list of bound shifts */
+ EGLPNUM_TYPENAME_coefinfo *cchanges; /* list of coef shifts */
+ int pIratio; /* ratio tests */
+ int pIIratio;
+ int dIratio;
+ int dIIratio;
+
+ int maxiter;
+ int iterskip;
+ double maxtime;
+ double starttime;
+ struct EGLPNUM_TYPENAME_ILLlpdata *O;
+ ILLrandstate rstate;
+
+}
+EGLPNUM_TYPENAME_lpinfo;
+
+/* pricing structures */
+typedef struct
+{
+ int ninit;
+ EGLPNUM_TYPE *norms;
+ int *refframe;
+}
+EGLPNUM_TYPENAME_p_devex_info;
+
+typedef struct
+{
+ EGLPNUM_TYPE *norms;
+}
+EGLPNUM_TYPENAME_p_steep_info;
+
+typedef struct
+{
+ int k;
+ int cgroup;
+ int ngroups;
+ int *gstart;
+ int *gshift;
+ int *gsize;
+ int bsize;
+ int *bucket;
+ int *perm;
+ EGLPNUM_TYPE *infeas;
+}
+EGLPNUM_TYPENAME_mpart_info;
+
+typedef struct
+{
+ int ninit;
+ EGLPNUM_TYPE *norms;
+ int *refframe;
+}
+EGLPNUM_TYPENAME_d_devex_info;
+
+typedef struct
+{
+ EGLPNUM_TYPE *norms;
+}
+EGLPNUM_TYPENAME_d_steep_info;
+
+/* pricing information */
+typedef struct EGLPNUM_TYPENAME_price_info
+{
+ int p_strategy;
+ int d_strategy;
+ int pI_price;
+ int pII_price;
+ int dI_price;
+ int dII_price;
+ int cur_price;
+ EGLPNUM_TYPE *p_scaleinf;
+ EGLPNUM_TYPE *d_scaleinf;
+ EGLPNUM_TYPENAME_p_devex_info pdinfo;
+ EGLPNUM_TYPENAME_p_steep_info psinfo;
+ EGLPNUM_TYPENAME_mpart_info pmpinfo;
+ EGLPNUM_TYPENAME_d_devex_info ddinfo;
+ EGLPNUM_TYPENAME_d_steep_info dsinfo;
+ EGLPNUM_TYPENAME_mpart_info dmpinfo;
+ EGLPNUM_TYPENAME_heap h;
+ EGLPNUM_TYPE htrigger;
+ int hineff;
+ char init;
+}
+EGLPNUM_TYPENAME_price_info;
+
+#endif /* EGLPNUM_TYPENAME___QS_LPDEFS_H */
diff --git a/qsopt_ex/mps.c b/qsopt_ex/mps.c
new file mode 100644
index 0000000..65afcad
--- /dev/null
+++ b/qsopt_ex/mps.c
@@ -0,0 +1,1350 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: mps.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+
+/****************************************************************************/
+/* */
+/* Routines for Reading and Writing MPS Files */
+/* */
+/* EXPORTED FUNCTIONS */
+/* */
+/* int ILLlpdata_mpsread (EGLPNUM_TYPENAME_ILLlpdata *lp, const char *filename); */
+/* int ILLlpdata_mpswrite(EGLPNUM_TYPENAME_ILLlpdata *lp, const char *filename); */
+/* */
+/* NOTES */
+/* */
+/* In the MPS reader, integer variables without an explicit bound are */
+/* set to binary; real variables without an explict lower bound and */
+/* either a nonnegative or free upperbound set to nonnegative. (These */
+/* are standard settings.) */
+/* */
+/* If a RHS is not specified for a row, it is set to 0. */
+/* */
+/* The MPS reader allows CPLEX's OBJSENSE extension to specify max or */
+/* min and the OBJNAME extension to specify an objective row. */
+/* */
+/****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "eg_lpnum.h"
+#include "eg_io.h"
+
+#include "except.h"
+#include "util.h"
+#include "names.h"
+#include "mps_EGLPNUM_TYPENAME.h"
+#include "rawlp_EGLPNUM_TYPENAME.h"
+#include "lpdata_EGLPNUM_TYPENAME.h"
+//extern EGLPNUM_TYPE EGLPNUM_TYPENAME_SZERO_TOLER;
+
+
+static int TRACE = 0;
+
+const char *EGLPNUM_TYPENAME_ILLmps_section_name[ILL_MPS_N_SECTIONS + 2] = {
+ "NAME", "OBJSENSE", "OBJNAME", "ROWS", "COLUMNS",
+ "RHS", "RANGES", "BOUNDS", "REFROW", "ENDATA",
+ NULL
+};
+
+static const char *mps_bound_name[] = {
+ "LO", "UP", "FX", "FR", "MI", "PL", "BV", "UI", "LI", NULL
+};
+
+/****************************************************************************/
+/* reading
+ */
+static int read_mps_section (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp);
+
+static int read_mps_name (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp);
+static int read_mps_refrow (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp);
+static int read_mps_objnamesense (
+ ILLmps_section sec,
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp);
+static int read_mps_objname (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state);
+static int read_mps_objsense (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp);
+
+static int read_mps_line_in_section (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp);
+
+
+static int add_row (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp);
+static int add_col (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp);
+static int add_rhs (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp);
+static int add_ranges (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp);
+static int add_bounds (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp);
+
+static int mps_read_marker_line (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp);
+static int is_marker_line (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state);
+static int mps_read_col_line (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp);
+
+static int mps_fill_in (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ const char *obj);
+
+
+static void mps_set_bound (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ int colind,
+ const char *bndtype,
+ EGLPNUM_TYPE bnd);
+
+int EGLPNUM_TYPENAME_ILLread_mps (
+ EGLPNUM_TYPENAME_qsline_reader * file,
+ const char *f,
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+ int rval = 0;
+ int end = 0;
+ EGLPNUM_TYPENAME_ILLread_mps_state state;
+
+ ILL_IFTRACE ("\tread_mps\n");
+ if (ILLsymboltab_create (&lp->rowtab, 100) ||
+ ILLsymboltab_create (&lp->coltab, 100))
+ {
+ rval = 1;
+ }
+ else
+ {
+ rval = EGLPNUM_TYPENAME_ILLmps_state_init (&state, file, f);
+ }
+ if (rval != 0)
+ {
+ goto CLEANUP;
+ }
+
+ while (EGLPNUM_TYPENAME_ILLmps_next_line (&state) == 0)
+ {
+ if (EGLPNUM_TYPENAME_ILLmps_empty_key (&state))
+ {
+ if (read_mps_line_in_section (&state, lp) != 0)
+ {
+ rval++;
+ }
+ }
+ else
+ {
+ /* found a section indicator in col 1 */
+ if (!strcmp (state.key, EGLPNUM_TYPENAME_ILLmps_section_name[ILL_MPS_ENDATA]))
+ {
+ end = 1;
+ break; /* done reading */
+ }
+ if (read_mps_section (&state, lp) != 0)
+ {
+ rval++;
+ }
+ }
+ if (rval == 50)
+ {
+ (void) EGLPNUM_TYPENAME_ILLmps_error (&state, "Too many errors.\n");
+ }
+ }
+
+ if (!end)
+ {
+ EGLPNUM_TYPENAME_ILLmps_warn (&state, "Missing ENDATA.");
+ }
+ if (!EGLPNUM_TYPENAME_ILLmps_next_line (&state))
+ {
+ EGLPNUM_TYPENAME_ILLmps_warn (&state, "Ignoring text after ENDATA.");
+ }
+ if (rval == 0)
+ {
+ rval = mps_fill_in (lp, state.obj);
+ }
+
+CLEANUP:
+ ILL_RESULT (rval, "read_mps");
+}
+
+static int check_section_order (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ int sec)
+{
+ switch (sec)
+ {
+ case ILL_MPS_REFROW:
+ if (state->section[ILL_MPS_ROWS] == 1)
+ {
+ return EGLPNUM_TYPENAME_ILLmps_error (state, "%s section after ROWS section.\n",
+ EGLPNUM_TYPENAME_ILLmps_section_name[sec]);
+ }
+ break;
+
+ case ILL_MPS_COLS:
+ case ILL_MPS_RHS:
+ case ILL_MPS_RANGES:
+ if (state->section[ILL_MPS_ROWS] == 0)
+ {
+ return EGLPNUM_TYPENAME_ILLmps_error (state, "%s section before ROWS section.\n",
+ EGLPNUM_TYPENAME_ILLmps_section_name[sec]);
+ };
+ break;
+
+ case ILL_MPS_BOUNDS:
+ if (state->section[ILL_MPS_COLS] == 0)
+ {
+ return EGLPNUM_TYPENAME_ILLmps_error (state, "%s section before COLUMNS section.\n",
+ EGLPNUM_TYPENAME_ILLmps_section_name[sec]);
+ }
+ break;
+ }
+ return 0;
+}
+
+static int read_mps_section (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+ int sec;
+ int rval = 0, r;
+
+ ILL_FAILtrue (EGLPNUM_TYPENAME_ILLmps_empty_key (state), "must have a key on this line");
+
+ sec = ILLutil_index (EGLPNUM_TYPENAME_ILLmps_section_name, state->key);
+ if (sec < 0)
+ {
+ return EGLPNUM_TYPENAME_ILLmps_error (state, "\"%s\" is not a key.\n", state->key);
+ }
+ rval = EGLPNUM_TYPENAME_ILLmps_set_section (state, sec);
+
+ state->active = ILL_MPS_NONE;
+ rval = rval || check_section_order (state, sec);
+ switch (sec)
+ {
+ case ILL_MPS_COLS:
+ case ILL_MPS_ROWS:
+ state->active = sec;
+ break;
+
+ case ILL_MPS_NAME:
+ if (rval == 0)
+ {
+ rval = read_mps_name (state, lp);
+ }
+ break;
+
+ case ILL_MPS_RHS:
+ if (rval == 0)
+ {
+ rval = EGLPNUM_TYPENAME_ILLraw_init_rhs (lp);
+ }
+ state->active = ILL_MPS_RHS;
+ break;
+
+ case ILL_MPS_RANGES:
+ if (rval == 0)
+ {
+ rval = EGLPNUM_TYPENAME_ILLraw_init_ranges (lp);
+ }
+ state->active = ILL_MPS_RANGES;
+ break;
+
+ case ILL_MPS_BOUNDS:
+ if (rval == 0)
+ {
+ rval = EGLPNUM_TYPENAME_ILLraw_init_bounds (lp);
+ }
+ state->active = ILL_MPS_BOUNDS;
+ break;
+
+ case ILL_MPS_OBJNAME:
+ case ILL_MPS_OBJSENSE:
+ r = read_mps_objnamesense (sec, state, lp);
+ rval = r || rval;
+ break;
+
+ case ILL_MPS_REFROW:
+ r = read_mps_refrow (state, lp);
+ rval = r || rval;
+ break;
+
+ default:
+ ILL_REPRT ("should never get here");
+ goto CLEANUP;
+ }
+CLEANUP:
+ ILL_RESULT (rval, "read_mps_section");
+}
+
+static int read_mps_name (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+ int rval = 0;
+
+ if (EGLPNUM_TYPENAME_ILLmps_empty_field (state))
+ {
+ EGLPNUM_TYPENAME_ILLmps_warn (state, "Blank NAME.");
+ }
+ else
+ {
+ ILL_UTIL_STR (lp->name, state->field);
+ }
+CLEANUP:
+ ILL_RESULT (rval, "read_mps_name");
+}
+
+static int read_mps_refrow (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+ int rval = 0;
+
+ rval = EGLPNUM_TYPENAME_ILLmps_next_line (state);
+ if (state->section[ILL_MPS_REFROW] > 1)
+ {
+ /* this is the second time we see this section;
+ * don't complain about errors */
+ return 0;
+ }
+ if (EGLPNUM_TYPENAME_ILLmps_empty_key (state) && !EGLPNUM_TYPENAME_ILLmps_empty_field (state))
+ {
+ ILL_UTIL_STR (lp->refrow, state->field);
+ return 0;
+ }
+ else
+ {
+ return EGLPNUM_TYPENAME_ILLmps_error (state, "Bad row name in REFROW section.\n");
+ }
+CLEANUP:
+ ILL_RETURN (rval, "read_mps_refrow");
+}
+
+static int read_mps_objnamesense (
+ ILLmps_section sec,
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+ if (state->section[sec] > 1)
+ {
+ /* this is the second time we see this section; just skip next line */
+ (void) EGLPNUM_TYPENAME_ILLmps_next_line (state);
+ return 0;
+ }
+ if (EGLPNUM_TYPENAME_ILLmps_next_line (state) != 0)
+ {
+ return EGLPNUM_TYPENAME_ILLmps_error (state, "Missing %s line at end of file.\n",
+ EGLPNUM_TYPENAME_ILLmps_section_name[sec]);
+ }
+ if ((!EGLPNUM_TYPENAME_ILLmps_empty_key (state)) || EGLPNUM_TYPENAME_ILLmps_empty_field (state))
+ {
+ (void) EGLPNUM_TYPENAME_ILLmps_error (state, "Bad %s in %s record.\n",
+ ((sec == ILL_MPS_OBJNAME) ? "row name"
+ : "objective sense"), EGLPNUM_TYPENAME_ILLmps_section_name[sec]);
+ if (!EGLPNUM_TYPENAME_ILLmps_empty_key (state))
+ {
+ (void) read_mps_section (state, lp);
+ }
+ return 1;
+ }
+ if (sec == ILL_MPS_OBJNAME)
+ {
+ if (read_mps_objname (state))
+ {
+ return 1;
+ }
+ }
+ else
+ {
+ if (read_mps_objsense (state, lp) != 0)
+ {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int read_mps_objsense (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+ int rval = 0;
+ char *objsense = state->field;
+
+ ILL_FAILfalse (state->section[ILL_MPS_OBJSENSE] == 1, "should never happen");
+ if (!strcmp (objsense, "MAX") ||
+ !strcmp (objsense, "Max") ||
+ !strcmp (objsense, "max") ||
+ !strcmp (objsense, "MAXIMIZE") ||
+ !strcmp (objsense, "Maximize") || !strcmp (objsense, "maximize"))
+ {
+ lp->objsense = EGLPNUM_TYPENAME_ILL_MAX;
+ }
+ else if (!strcmp (objsense, "MIN") ||
+ !strcmp (objsense, "Min") ||
+ !strcmp (objsense, "min") ||
+ !strcmp (objsense, "MINIMIZE") ||
+ !strcmp (objsense, "Minimize") || !strcmp (objsense, "minimize"))
+ {
+ lp->objsense = EGLPNUM_TYPENAME_ILL_MIN;
+ }
+ else
+ {
+ return EGLPNUM_TYPENAME_ILLmps_error (state, "\"%s\" is no OBJSENSE.\n", objsense);
+ }
+CLEANUP:
+ ILL_RESULT (rval, "read_mps_objsense");
+}
+
+static int read_mps_objname (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state)
+{
+ int rval = 0;
+
+ ILL_FAILfalse (state->section[ILL_MPS_OBJNAME] == 1, "should never happen");
+ ILL_UTIL_STR (state->obj, state->field);
+CLEANUP:
+ ILL_RETURN (rval, "read_mps_objname");
+}
+
+static int read_mps_line_in_section (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+ int rval = 0;
+
+ ILL_FAILtrue (!EGLPNUM_TYPENAME_ILLmps_empty_key (state) || EGLPNUM_TYPENAME_ILLmps_empty_field (state),
+ "no key but at least one field on state->line");
+
+ if (state->active == ILL_MPS_NONE)
+ {
+ return EGLPNUM_TYPENAME_ILLmps_error (state, "Line is in no section.\n");
+ }
+ else
+ {
+ if (state->section[state->active] == 1)
+ {
+ switch (state->active)
+ {
+ case ILL_MPS_ROWS:
+ rval = add_row (state, lp);
+ break;
+ case ILL_MPS_COLS:
+ rval = add_col (state, lp);
+ break;
+ case ILL_MPS_RHS:
+ rval = add_rhs (state, lp);
+ break;
+ case ILL_MPS_RANGES:
+ rval = add_ranges (state, lp);
+ break;
+ case ILL_MPS_BOUNDS:
+ rval = add_bounds (state, lp);
+ break;
+ default:
+ ILL_REPRT ("should never get here");
+ ILL_CLEANUP;
+ }
+ if (rval == 0)
+ {
+ /* see whether there are extra fields on line */
+ EGLPNUM_TYPENAME_ILLmps_check_end_of_line (state);
+ }
+ }
+ }
+CLEANUP:
+ ILL_RESULT (rval, "read_mps_line_in_section");
+}
+
+static int add_row (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+ int ind, hit, rval = 0;
+ char sense;
+
+ ILL_FAILtrue (!EGLPNUM_TYPENAME_ILLmps_empty_key (state) || EGLPNUM_TYPENAME_ILLmps_empty_field (state),
+ "no key but at least one field on state->line");
+
+ /* field should contain exactly one character */
+ if (state->field[1] == '\0')
+ {
+ sense = state->field[0];
+ if (sense != 'L' && sense != 'G' && sense != 'E' && sense != 'N')
+ {
+ return EGLPNUM_TYPENAME_ILLmps_error (state,
+ "Unknown rowsense '%c' in ROWS record.\n", sense);
+ }
+ if (EGLPNUM_TYPENAME_ILLmps_next_field (state) == 0)
+ {
+ hit = ILLsymboltab_lookup (&lp->rowtab, state->field, &ind);
+ if (!hit)
+ {
+ rval = EGLPNUM_TYPENAME_ILLmps_error (state,
+ "Repeated row definition for \"%s\".\n",
+ state->field);
+ }
+ else
+ {
+ rval = EGLPNUM_TYPENAME_ILLraw_add_row (lp, state->field, sense, EGLPNUM_TYPENAME_zeroLpNum); /* default rhs is 0.0 */
+ }
+ }
+ else
+ {
+ rval = EGLPNUM_TYPENAME_ILLmps_error (state, "Missing rowname in ROWS record.\n");
+ }
+ }
+ else
+ {
+ rval = EGLPNUM_TYPENAME_ILLmps_error (state, "Unknown rowsense '%s' in ROWS record.\n",
+ state->field);
+ }
+CLEANUP:
+ ILL_RESULT (rval, "add_row");
+}
+
+static int add_col (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+ int rval = 0;
+
+ ILL_FAILtrue (!EGLPNUM_TYPENAME_ILLmps_empty_key (state) || EGLPNUM_TYPENAME_ILLmps_empty_field (state),
+ "no key but at least one field on state->line");
+
+ if (is_marker_line (state))
+ {
+ return mps_read_marker_line (state, lp);
+ }
+ else
+ {
+ return mps_read_col_line (state, lp);
+ }
+CLEANUP:
+ ILL_RETURN (rval, "add_col");
+}
+
+static int mps_read_col_line (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+ int hit, colind, rowind, rval = 0, more, ind;
+ EGLPNUM_TYPE ncoef;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (ncoef);
+
+ ILL_FAILtrue (!EGLPNUM_TYPENAME_ILLmps_empty_key (state) || EGLPNUM_TYPENAME_ILLmps_empty_field (state),
+ "no key but at least one field on state->line");
+
+ hit = ILLsymboltab_lookup (&lp->coltab, state->field, &colind);
+ if (hit)
+ {
+ rval = EGLPNUM_TYPENAME_ILLraw_add_col (lp, state->field, state->intvar);
+ ILL_CLEANUP_IF (rval);
+ colind = lp->ncols - 1;
+ }
+ else
+ {
+ if (state->intvar)
+ {
+ /*previously declared variable is in integer section */
+ lp->intmarker[colind] = 1;
+ }
+ }
+#ifndef NDEBUG
+ hit = ILLsymboltab_lookup (&lp->coltab, state->field, &ind);
+ ILL_FAILfalse (colind == ind, "colind should be index of state->field");
+#endif
+ if (state->sosvar == 1)
+ {
+ if (EGLPNUM_TYPENAME_ILLraw_is_mem_other_sos (lp, colind))
+ {
+ rval = EGLPNUM_TYPENAME_ILLmps_error (state,
+ "\"%s\" is a member of SOS set #%d.\n",
+ EGLPNUM_TYPENAME_ILLraw_colname (lp, colind),
+ lp->is_sos_member[colind] + 1);
+ }
+ else
+ {
+ rval = EGLPNUM_TYPENAME_ILLraw_add_sos_member (lp, colind);
+ }
+ ILL_CLEANUP_IF (rval);
+ }
+
+ more = (EGLPNUM_TYPENAME_ILLmps_next_field (state) == 0);
+ if (!more)
+ {
+ return EGLPNUM_TYPENAME_ILLmps_error (state, "Missing fields in COLUMNS record.\n");
+ }
+ for (more = 1; more; more = (EGLPNUM_TYPENAME_ILLmps_next_field (state) == 0))
+ {
+ hit = ILLsymboltab_lookup (&lp->rowtab, state->field, &rowind);
+ if (hit)
+ {
+ return EGLPNUM_TYPENAME_ILLmps_error (state, "\"%s\" is not a row name.\n", state->field);
+ }
+ if (EGLPNUM_TYPENAME_ILLmps_next_coef (state, &ncoef) != 0)
+ {
+ return EGLPNUM_TYPENAME_ILLmps_error (state,
+ "Missing/Bad coefficient in COLUMNS record.\n");
+ }
+ rval = EGLPNUM_TYPENAME_ILLraw_add_col_coef (lp, colind, rowind, ncoef);
+ }
+CLEANUP:
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ncoef);
+ ILL_RESULT (rval, "mps_read_col_line");
+}
+
+static int is_marker_line (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state)
+{
+ const char *field = state->line;
+
+ while ((field = ILLutil_strchr (field, '\'')))
+ {
+ if (strncmp (field, "'MARKER'", (size_t) 8) == 0)
+ {
+ return 1;
+ }
+ while ((!EGLPNUM_TYPENAME_ILL_ISBLANK (field)) && (*field != '\0'))
+ {
+ field++;
+ }
+ }
+ return 0;
+}
+
+static int mps_read_marker_line (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+ int rval = 0;
+ int sos_type = EGLPNUM_TYPENAME_ILL_SOS_TYPE1;
+ int sos_line = 0;
+ int cur_sos_mode = state->sosvar;
+
+ if (strcmp (state->field, "S2") == 0)
+ {
+ sos_type = EGLPNUM_TYPENAME_ILL_SOS_TYPE2;
+ sos_line = 1;
+ }
+ else if (strcmp (state->field, "S1") == 0)
+ {
+ sos_line = 1;
+ }
+ if (sos_line)
+ {
+ rval = EGLPNUM_TYPENAME_ILLmps_next_field (state);
+ }
+ rval = rval || EGLPNUM_TYPENAME_ILLmps_next_field (state); /* swallow marker-id */
+ if (strcmp (state->field, "'MARKER'"))
+ {
+ return EGLPNUM_TYPENAME_ILLmps_error (state, "Bad 'MARKER' line.\n");
+ }
+ if (EGLPNUM_TYPENAME_ILLmps_next_field (state))
+ {
+ return EGLPNUM_TYPENAME_ILLmps_error (state, "Missing field on 'MARKER' line.\n");
+ }
+ rval = EGLPNUM_TYPENAME_ILLmps_int_sos_mode (state);
+ if (rval == 0)
+ {
+ if (cur_sos_mode != state->sosvar)
+ {
+ if (state->sosvar)
+ {
+ /* beginning of a new set */
+ rval = EGLPNUM_TYPENAME_ILLraw_add_sos (lp, sos_type);
+ }
+ }
+ }
+ ILL_RESULT (rval, "mps_read_marker_line");
+}
+
+static int add_rhs (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+ int rowind, more_fields, skip;
+ const char *rhsname;
+ EGLPNUM_TYPE rhs;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (rhs);
+
+ rhsname = EGLPNUM_TYPENAME_ILLmps_possibly_blank_name (state->field, state, &lp->rowtab);
+ if (EGLPNUM_TYPENAME_ILLraw_set_rhs_name (lp, rhsname, &skip))
+ {
+ EGLPNUM_TYPENAME_ILLmps_error (state, "Could not add right hand side.\n");
+ }
+
+ if (skip)
+ {
+ EGLPNUM_TYPENAME_ILLmps_set_end_of_line (state); /* to avoid warning about extra fields */
+ }
+ else
+ {
+ if (strcmp (rhsname, " "))
+ {
+ /* field is non blank rhs name; advance to row name */
+ if (EGLPNUM_TYPENAME_ILLmps_next_field (state))
+ {
+ return EGLPNUM_TYPENAME_ILLmps_error (state, "Missing row name in RHS record.\n");
+ }
+ }
+ for (more_fields = 1; more_fields; more_fields = !EGLPNUM_TYPENAME_ILLmps_next_field (state))
+ {
+ if (ILLsymboltab_lookup (&lp->rowtab, state->field, &rowind))
+ {
+ return EGLPNUM_TYPENAME_ILLmps_error (state, "\"%s\" is not a row name.\n",
+ state->field);
+ }
+ if (EGLPNUM_TYPENAME_ILLmps_next_coef (state, &rhs))
+ {
+ return EGLPNUM_TYPENAME_ILLmps_error (state, "Missing/Bad coefficient in RHS record.\n");
+ }
+ if (lp->rhsind[rowind])
+ {
+ return EGLPNUM_TYPENAME_ILLmps_error (state, "Two rhs values for row \"%s\".\n",
+ state->field);
+ }
+ else
+ {
+ if (lp->rowsense[rowind] == 'N')
+ {
+ EGLPNUM_TYPENAME_ILLmps_warn (state,
+ "Ignoring right hand side for N-row \"%s\".",
+ EGLPNUM_TYPENAME_ILLraw_rowname (lp, rowind));
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->rhs[rowind], rhs);
+ lp->rhsind[rowind] = 1;
+ }
+ }
+ }
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (rhs);
+ return 0;
+}
+
+static int add_bounds (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+ char bndtype[3];
+ const char *bounds_name;
+ int colind, skip, rval = 0;
+ EGLPNUM_TYPE bnd;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (bnd);
+
+ ILL_FAILtrue (!EGLPNUM_TYPENAME_ILLmps_empty_key (state) || EGLPNUM_TYPENAME_ILLmps_empty_field (state),
+ "no key but at least one field on state->line");
+
+ if (ILLutil_index (mps_bound_name, state->field) < 0)
+ {
+ return EGLPNUM_TYPENAME_ILLmps_error (state, "\"%s\" is not a BOUNDS type.\n", state->field);
+ }
+ strcpy (bndtype, state->field);
+
+ if (EGLPNUM_TYPENAME_ILLmps_next_field (state) != 0)
+ {
+ return EGLPNUM_TYPENAME_ILLmps_error (state,
+ "No bounds/column identifier in BOUNDS record.\n");
+ }
+
+ bounds_name = EGLPNUM_TYPENAME_ILLmps_possibly_blank_name (state->field, state, &lp->coltab);
+ if (bounds_name == NULL)
+ {
+ return 1;
+ }
+ if (EGLPNUM_TYPENAME_ILLraw_set_bounds_name (lp, bounds_name, &skip))
+ {
+ return 1;
+ }
+ if (skip)
+ {
+ EGLPNUM_TYPENAME_ILLmps_set_end_of_line (state); /* to avoid warning about extra fields */
+ }
+ else
+ {
+ if (strcmp (bounds_name, " "))
+ {
+ /* non empty bounds_name ==> advance to col name field */
+ if (EGLPNUM_TYPENAME_ILLmps_next_field (state))
+ {
+ return EGLPNUM_TYPENAME_ILLmps_error (state, "Missing column field in BOUNDS record.\n");
+ }
+ }
+ if (ILLsymboltab_lookup (&lp->coltab, state->field, &colind))
+ {
+ return EGLPNUM_TYPENAME_ILLmps_error (state, "\"%s\" is not a column name.\n",
+ state->field);
+ }
+ EGLPNUM_TYPENAME_EGlpNumZero (bnd);
+ if (strcmp (bndtype, "FR") && strcmp (bndtype, "BV") &&
+ strcmp (bndtype, "MI") && strcmp (bndtype, "PL"))
+ {
+ /* neither "FR", "BV", "MI" nor "PL" ==> there should be a bound */
+ if (EGLPNUM_TYPENAME_ILLmps_next_bound (state, &bnd))
+ {
+ return EGLPNUM_TYPENAME_ILLmps_error (state,
+ "Missing/Bad bound field in BOUNDS record.\n");
+ }
+ }
+ mps_set_bound (lp, state, colind, bndtype, bnd);
+ }
+CLEANUP:
+ EGLPNUM_TYPENAME_EGlpNumClearVar (bnd);
+ ILL_RESULT (rval, "add_bounds");
+}
+
+static void mps_set_bound (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ int colind,
+ const char *bndtype,
+ EGLPNUM_TYPE bnd)
+{
+ const char *msg = NULL;
+
+ if (!strcmp (bndtype, "LO"))
+ {
+ msg = EGLPNUM_TYPENAME_ILLraw_set_lowerBound (lp, colind, bnd);
+ }
+ else if (!strcmp (bndtype, "UP"))
+ {
+ msg = EGLPNUM_TYPENAME_ILLraw_set_upperBound (lp, colind, bnd);
+ }
+ else if (!strcmp (bndtype, "FX"))
+ {
+ msg = EGLPNUM_TYPENAME_ILLraw_set_fixedBound (lp, colind, bnd);
+ }
+ else if (!strcmp (bndtype, "FR"))
+ {
+ msg = EGLPNUM_TYPENAME_ILLraw_set_unbound (lp, colind);
+ }
+ else if (!strcmp (bndtype, "BV"))
+ {
+ msg = EGLPNUM_TYPENAME_ILLraw_set_binaryBound (lp, colind);
+ if (msg == NULL)
+ {
+ lp->intmarker[colind] = 1;
+ }
+ }
+ else if (!strcmp (bndtype, "UI"))
+ {
+ msg = EGLPNUM_TYPENAME_ILLraw_set_upperBound (lp, colind, bnd);
+ if (msg == NULL)
+ {
+ lp->intmarker[colind] = 1;
+ }
+ }
+ else if (!strcmp (bndtype, "LI"))
+ {
+ msg = EGLPNUM_TYPENAME_ILLraw_set_lowerBound (lp, colind, bnd);
+ if (msg == NULL)
+ {
+ lp->intmarker[colind] = 1;
+ }
+ }
+ else if (!strcmp (bndtype, "MI"))
+ {
+ msg = EGLPNUM_TYPENAME_ILLraw_set_lowerBound (lp, colind, EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+ }
+ else if (!strcmp (bndtype, "PL"))
+ {
+ msg = EGLPNUM_TYPENAME_ILLraw_set_upperBound (lp, colind, EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+ }
+ else
+ {
+ ILL_REPRT ("should never get here");
+ ILL_CLEANUP;
+ }
+ EGLPNUM_TYPENAME_ILLmps_warn (state, msg);
+CLEANUP:
+ return;
+}
+
+static int add_ranges (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+ const char *rangesname;
+ int skip, more_fields, rowind;
+ EGLPNUM_TYPE ntmp;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (ntmp);
+
+ rangesname = EGLPNUM_TYPENAME_ILLmps_possibly_blank_name (state->field, state, &lp->rowtab);
+ if (EGLPNUM_TYPENAME_ILLraw_set_ranges_name (lp, rangesname, &skip))
+ {
+ return EGLPNUM_TYPENAME_ILLmps_error (state, "Could not add range.\n");
+ }
+ if (skip)
+ {
+ EGLPNUM_TYPENAME_ILLmps_set_end_of_line (state); /* to avoid warning about extra fields */
+ }
+ else
+ {
+ if (strcmp (rangesname, " "))
+ {
+ /* field is non blank ranges name; advance to row name */
+ if (EGLPNUM_TYPENAME_ILLmps_next_field (state))
+ {
+ return EGLPNUM_TYPENAME_ILLmps_error (state, "Missing row name in RANGES record.");
+ }
+ }
+ for (more_fields = 1; more_fields; more_fields = !EGLPNUM_TYPENAME_ILLmps_next_field (state))
+ {
+ if (ILLsymboltab_lookup (&lp->rowtab, state->field, &rowind))
+ {
+ return EGLPNUM_TYPENAME_ILLmps_error (state, "\"%s\" is not a row name.\n",
+ state->field);
+ }
+ if (EGLPNUM_TYPENAME_ILLmps_next_coef (state, &ntmp))
+ {
+ return EGLPNUM_TYPENAME_ILLmps_error (state,
+ "Missing/Bad coefficient in RANGES record.\n");
+ }
+ if (lp->rangesind[rowind])
+ {
+ EGLPNUM_TYPENAME_ILLmps_warn (state, "Ignoring second RANGE value %s \"%s\".",
+ "for row", EGLPNUM_TYPENAME_ILLraw_rowname (lp, rowind));
+ }
+ else
+ {
+ if (lp->rowsense[rowind] != 'N')
+ {
+ if (EGLPNUM_TYPENAME_ILLraw_add_ranges_coef (lp, rowind, ntmp))
+ return 1;
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_ILLmps_warn (state, "Ignoring RANGE value for N-row \"%s\".",
+ EGLPNUM_TYPENAME_ILLraw_rowname (lp, rowind));
+ }
+ }
+ }
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+ return 0;
+}
+
+
+static int mps_fill_in (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ const char *obj)
+{
+ int i, hit, rval = 0;
+
+ /* find the objective function -- the first N row if obj is not defined */
+ if (obj)
+ {
+ hit = ILLsymboltab_lookup (&lp->rowtab, obj, &lp->objindex);
+ if (hit)
+ {
+ return EGLPNUM_TYPENAME_ILLdata_error (lp->error_collector,
+ "Bad objective name \"%s\".\n", obj);
+ }
+ else if (lp->rowsense[lp->objindex] != 'N')
+ {
+ EGLPNUM_TYPENAME_ILLdata_warn (lp->error_collector,
+ "Making objective row \"%s\" a N-row.", obj);
+ }
+ lp->rowsense[lp->objindex] = 'N';
+ }
+ else
+ {
+ for (i = 0; i < lp->nrows; i++)
+ {
+ if (lp->rowsense[i] == 'N')
+ {
+ lp->objindex = i;
+ break;
+ }
+ }
+ if (i == lp->nrows)
+ {
+ return EGLPNUM_TYPENAME_ILLdata_error (lp->error_collector,
+ "No N-row in lp definition.\n");
+ }
+ }
+
+ if (lp->ncols > 0)
+ {
+ rval = EGLPNUM_TYPENAME_ILLraw_fill_in_bounds (lp);
+ }
+
+ /* set weights of sos set members */
+ if (lp->refrow)
+ {
+ /* take the values from refrow */
+ EGLPNUM_TYPE weight;
+ EGLPNUM_TYPENAME_colptr *cp;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (weight);
+
+ hit = ILLsymboltab_lookup (&lp->rowtab, lp->refrow, &lp->refrowind);
+ if (hit)
+ {
+ return EGLPNUM_TYPENAME_ILLdata_error (lp->error_collector,
+ "REFROW \"%s\" is not a row name.\n", lp->refrow);
+ }
+ for (i = 0; i < lp->nsos_member; i++)
+ {
+ for (cp = lp->cols[lp->sos_col[i]]; cp != NULL; cp = cp->next)
+ {
+ if (cp->this_val == lp->refrowind)
+ break;
+ }
+ if ((cp != NULL) && EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (cp->coef))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (weight, cp->coef);
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_ILLdata_warn (lp->error_collector,
+ "\"%s\" has 0.0 coefficient in REFROW \"%s\".",
+ EGLPNUM_TYPENAME_ILLraw_colname (lp, lp->sos_col[i]), lp->refrow);
+ EGLPNUM_TYPENAME_EGlpNumZero (weight);
+ }
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->sos_weight[i], weight);
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (weight);
+ }
+ else
+ { /* no refrow */
+ /* set weights to 1, 2, 3, ... in order of definition */
+ int si, w;
+ EGLPNUM_TYPENAME_sosptr *set;
+
+ for (si = 0; si < lp->nsos; si++)
+ {
+ set = lp->sos_set + si;
+ w = 1;
+ for (i = set->first; i < set->first + set->nelem; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumSet (lp->sos_weight[i], (double) w);
+ w++;
+ }
+ }
+ }
+ ILL_IFTRACE ("bound %lf <= x1 <= %lf\n", EGLPNUM_TYPENAME_EGlpNumToLf (lp->lower[0]),
+ EGLPNUM_TYPENAME_EGlpNumToLf (lp->upper[0]));
+ ILL_IFTRACE ("MAXDOUBLE %lf MINDOUBLE %lf\n", EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_ILL_MAXDOUBLE),
+ EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_ILL_MINDOUBLE));
+ ILL_RESULT (rval, "mps_fill_in");
+}
+
+/****************************************************************************/
+/* writing
+ */
+
+static int mps_write_col (
+ int i,
+ int iorig,
+ char *colname,
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ char **rownames,
+ int intmode,
+ char *objname);
+
+int EGLPNUM_TYPENAME_ILLwrite_mps (
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ EGLPNUM_TYPENAME_qserror_collector * collector)
+{
+ int rval = 0;
+ int marker = 0;
+ int intmode = 0;
+ int i, ri, set, el, empty, prtLower, prtUpper;
+ char **colnames = (char **) NULL;
+ char **rownames = (char **) NULL;
+ EGLPNUM_TYPENAME_ILLlp_rows lp_rows, *lprows = NULL;
+ char buf[ILL_namebufsize];
+ char *objname = NULL;
+ char *str;
+
+ ILL_CHECKnull (lp, "lp must not be null");
+ ILL_FAILtrue (lp->probname == NULL, "oops should never happen");
+
+ ILL_FAILfalse (lp->colnames != NULL, "colnames != NULL");
+ ILL_FAILfalse (lp->rownames != NULL, "colnames != NULL");
+ colnames = lp->colnames;
+ rownames = lp->rownames;
+
+ objname = lp->objname;
+ if (objname == (char *) NULL)
+ {
+ strcpy (buf, "obj");
+ rval = ILLsymboltab_uname (&lp->rowtab, buf, "", NULL);
+ ILL_CLEANUP_IF (rval);
+ ILL_UTIL_STR (objname, buf);
+ }
+ EGLPNUM_TYPENAME_ILLprint_report (lp, "NAME %s\n", lp->probname);
+ EGLPNUM_TYPENAME_ILLprint_report (lp, "OBJSENSE\n %s\n",
+ (lp->objsense == EGLPNUM_TYPENAME_ILL_MIN) ? "MIN" : "MAX");
+ EGLPNUM_TYPENAME_ILLprint_report (lp, "OBJNAME\n %s\n", objname);
+ if (lp->refrowname)
+ {
+ EGLPNUM_TYPENAME_ILLprint_report (lp, "REFROW\n");
+ EGLPNUM_TYPENAME_ILLprint_report (lp, " %s\n", lp->refrowname);
+ }
+
+
+ EGLPNUM_TYPENAME_ILLprint_report (lp, "ROWS\n");
+ EGLPNUM_TYPENAME_ILLprint_report (lp, " N %s\n", objname);
+ if (lp->refrowname && (lp->refind == -1))
+ {
+ EGLPNUM_TYPENAME_ILLprint_report (lp, " N %s\n", lp->refrowname);
+ }
+
+ lprows = &lp_rows;
+ rval = EGLPNUM_TYPENAME_ILLlp_rows_init (lprows, lp, 0);
+ ILL_CLEANUP_IF (rval);
+ for (i = 0; i < lp->nrows; i++)
+ {
+ if (lprows->rowcnt[i] == 0)
+ {
+ EGLPNUM_TYPENAME_ILLdata_warn (collector,
+ "Deleting empty row \"%s\" from constraints.", rownames[i]);
+ continue;
+ }
+ switch (lp->sense[i])
+ {
+ case 'G':
+ EGLPNUM_TYPENAME_ILLprint_report (lp, " G ");
+ break;
+ case 'L':
+ EGLPNUM_TYPENAME_ILLprint_report (lp, " L ");
+ break;
+ case 'E':
+ EGLPNUM_TYPENAME_ILLprint_report (lp, " E ");
+ break;
+ case 'R':
+ EGLPNUM_TYPENAME_ILLprint_report (lp, " G ");
+ break;
+ }
+ EGLPNUM_TYPENAME_ILLprint_report (lp, "%s\n", rownames[i]);
+ }
+
+ EGLPNUM_TYPENAME_ILLprint_report (lp, "COLUMNS\n");
+ for (set = 0; set < lp->sos.matcols; set++)
+ {
+ ILL_FAILtrue (lp->sos_type == NULL, "must have non NULL sos_type");
+ ILL_FAILtrue (lp->is_sos_mem == NULL, "must have non NULL is_sos_mem");
+ empty = 1;
+ for (el = lp->sos.matbeg[set];
+ el < lp->sos.matbeg[set] + lp->sos.matcnt[set]; el++)
+ {
+ if (empty)
+ {
+ EGLPNUM_TYPENAME_ILLprint_report (lp, " %s SOS%dqs 'MARKER' 'SOSORG'\n",
+ ((lp->sos_type[set] == EGLPNUM_TYPENAME_ILL_SOS_TYPE1)) ? "S1" : "S2",
+ marker++);
+ empty = 0;
+ }
+ ri = lp->sos.matind[el];
+ i = lp->structmap[ri];
+ intmode = mps_write_col (i, ri, colnames[ri], lp, rownames,
+ intmode, objname);
+ if (lp->refrowname && (lp->refind == -1))
+ {
+ EGLPNUM_TYPENAME_ILLprint_report (lp, " %s %s %g\n",
+ colnames[ri], lp->refrowname, lp->sos.matval[el]);
+ }
+ }
+ if (!empty)
+ {
+ EGLPNUM_TYPENAME_ILLprint_report (lp, " SOS%dqs 'MARKER' 'SOSEND'\n", marker++);
+ }
+ }
+ for (ri = 0; ri < lp->nstruct; ri++)
+ {
+ if (lp->is_sos_mem == (int *) NULL || lp->is_sos_mem[ri] == -1)
+ {
+ i = lp->structmap[ri];
+ intmode = mps_write_col (i, ri, colnames[ri], lp, rownames,
+ intmode, objname);
+ }
+ }
+ if (intmode)
+ {
+ EGLPNUM_TYPENAME_ILLprint_report (lp, " MARK%dqs 'MARKER' 'INTEND'\n", lp->nstruct);
+ }
+
+ EGLPNUM_TYPENAME_ILLprint_report (lp, "RHS\n");
+ for (i = 0; i < lp->nrows; i++)
+ {
+ if ((lprows->rowcnt[i] != 0) && EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (lp->rhs[i]))
+ {
+ str = EGLPNUM_TYPENAME_EGlpNumGetStr(lp->rhs[i]);
+ EGLPNUM_TYPENAME_ILLprint_report (lp, " RHS %s %s\n", rownames[i], str);
+ EGfree(str);
+ }
+ }
+
+ if (lp->rangeval)
+ {
+ EGLPNUM_TYPENAME_ILLprint_report (lp, "RANGES\n");
+ for (i = 0; i < lp->nrows; i++)
+ {
+ if ((lprows->rowcnt[i] != 0) && EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (lp->rangeval[i]))
+ {
+ str = EGLPNUM_TYPENAME_EGlpNumGetStr(lp->rangeval[i]);
+ EGLPNUM_TYPENAME_ILLprint_report (lp, " RANGE %s %s\n", rownames[i], str);
+ EGfree(str);
+ }
+ }
+ }
+
+ ri = EGLPNUM_TYPENAME_ILLraw_first_nondefault_bound (lp);
+ if (ri != lp->nstruct)
+ {
+ EGLPNUM_TYPENAME_ILLprint_report (lp, "BOUNDS\n");
+ for (; ri < lp->nstruct; ri++)
+ {
+ i = lp->structmap[ri];
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (lp->lower[i], lp->upper[i]))
+ {
+ str = EGLPNUM_TYPENAME_EGlpNumGetStr(lp->lower[i]);
+ EGLPNUM_TYPENAME_ILLprint_report (lp, " FX BOUND %s %s\n", colnames[ri], str);
+ EGfree(str);
+ continue;
+ }
+ if ((EGLPNUM_TYPENAME_EGlpNumIsEqqual (lp->lower[i], EGLPNUM_TYPENAME_ILL_MINDOUBLE)) &&
+ (EGLPNUM_TYPENAME_EGlpNumIsEqqual (lp->upper[i], EGLPNUM_TYPENAME_ILL_MAXDOUBLE)))
+ {
+ EGLPNUM_TYPENAME_ILLprint_report (lp, " FR BOUND %s\n", colnames[ri]);
+ continue;
+ }
+ prtLower = !EGLPNUM_TYPENAME_ILLraw_default_lower (lp, i);
+ prtUpper = !EGLPNUM_TYPENAME_ILLraw_default_upper (lp, i, ri);
+ if (prtLower)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (lp->lower[i], EGLPNUM_TYPENAME_ILL_MINDOUBLE))
+ {
+ EGLPNUM_TYPENAME_ILLprint_report (lp, " MI BOUND %s\n", colnames[ri]);
+ }
+ else
+ {
+ str = EGLPNUM_TYPENAME_EGlpNumGetStr(lp->lower[i]);
+ EGLPNUM_TYPENAME_ILLprint_report (lp, " LO BOUND %s %s\n", colnames[ri], str);
+ EGfree(str);
+ }
+ }
+ if (prtUpper)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (lp->upper[i], EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+ {
+ EGLPNUM_TYPENAME_ILLprint_report (lp, " PL BOUND %s\n", colnames[ri]);
+ }
+ else
+ {
+ str = EGLPNUM_TYPENAME_EGlpNumGetStr(lp->upper[i]);
+ EGLPNUM_TYPENAME_ILLprint_report (lp, " UP BOUND %s %s\n", colnames[ri], str);
+ EGfree(str);
+ }
+ }
+ }
+ }
+ EGLPNUM_TYPENAME_ILLprint_report (lp, "ENDATA\n");
+
+CLEANUP:
+ EGLPNUM_TYPENAME_ILLlp_rows_clear (lprows);
+ if (!lp->colnames)
+ {
+ ILLfree_names (colnames, lp->ncols);
+ }
+ if (!lp->rownames)
+ {
+ ILLfree_names (rownames, lp->nrows);
+ }
+ if (objname != lp->objname)
+ {
+ ILL_IFFREE (objname, char);
+ }
+ ILL_RESULT (rval, "ILLlpdata_mpswrite");
+}
+
+static int mps_write_col (
+ int i,
+ int iorig,
+ char *colname,
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ char **rownames,
+ int intmode,
+ char *objname)
+{
+ int row, k;
+ char*str;
+ EGLPNUM_TYPENAME_ILLmatrix *A;
+
+ A = &lp->A;
+ if (lp->intmarker && (lp->intmarker[iorig] != intmode))
+ {
+ EGLPNUM_TYPENAME_ILLprint_report (lp, " MARK%dqs 'MARKER' '%s'\n", iorig,
+ (lp->intmarker[iorig] ? "INTORG" : "INTEND"));
+ intmode = lp->intmarker[iorig];
+ }
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (lp->obj[i]))
+ {
+ str = EGLPNUM_TYPENAME_EGlpNumGetStr(lp->obj[i]);
+ EGLPNUM_TYPENAME_ILLprint_report (lp, " %s %s %s\n", colname, objname, str);
+ EGfree(str);
+ }
+ for (k = A->matbeg[i]; k < A->matbeg[i] + A->matcnt[i]; k++)
+ {
+ row = A->matind[k];
+ str = EGLPNUM_TYPENAME_EGlpNumGetStr(A->matval[k]);
+ EGLPNUM_TYPENAME_ILLprint_report (lp, " %s %s %s\n", colname, rownames[row], str);
+ EGfree(str);
+ }
+ return intmode;
+}
diff --git a/qsopt_ex/mps.h b/qsopt_ex/mps.h
new file mode 100644
index 0000000..e0094dc
--- /dev/null
+++ b/qsopt_ex/mps.h
@@ -0,0 +1,53 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCSINFO $Id: mps_EGLPNUM_TYPENAME.h,v 1.2 2003/11/05 16:57:39 meven Exp $ */
+#ifndef EGLPNUM_TYPENAME_MPS_H
+#define EGLPNUM_TYPENAME_MPS_H
+
+#include "readline_EGLPNUM_TYPENAME.h"
+#include "format_EGLPNUM_TYPENAME.h"
+
+/****************************************************************************/
+/* */
+/* Routines to support Reading and Writing MPS Files */
+/* */
+/****************************************************************************/
+#include "basicdefs.h"
+extern const char *EGLPNUM_TYPENAME_ILLmps_section_name[ILL_MPS_N_SECTIONS + 2];
+
+#include "lpdata_EGLPNUM_TYPENAME.h"
+#include "rawlp_EGLPNUM_TYPENAME.h"
+#include "read_mps_EGLPNUM_TYPENAME.h"
+
+extern int EGLPNUM_TYPENAME_ILLread_mps (
+ EGLPNUM_TYPENAME_qsline_reader * file,
+ const char *filename,
+ EGLPNUM_TYPENAME_rawlpdata * lp);
+
+extern int EGLPNUM_TYPENAME_ILLwrite_mps (
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ EGLPNUM_TYPENAME_qserror_collector * collector);
+
+ /* use lp->reporter for output */
+
+#endif
diff --git a/qsopt_ex/names.c b/qsopt_ex/names.c
new file mode 100644
index 0000000..fed05df
--- /dev/null
+++ b/qsopt_ex/names.c
@@ -0,0 +1,102 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCSINFO $Id: names.c,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "names.h"
+
+#include "logging-private.h"
+
+#include "util.h"
+#include "except.h"
+#include "symtab.h"
+
+
+void ILLfree_names (
+ char **names,
+ int count)
+{
+ int i;
+
+ if (names)
+ {
+ for (i = 0; i < count; i++)
+ {
+ ILL_IFFREE (names[i], char);
+ }
+ ILL_IFFREE (names, char *);
+ }
+}
+
+int ILLgenerate_names (
+ char prefix,
+ int nnames,
+ char ***names)
+{
+ int rval = 0;
+ int i, len;
+ char *buf = (char *) NULL;
+
+ *names = (char **) NULL;
+ if (nnames == 0)
+ goto CLEANUP;
+
+ ILL_SAFE_MALLOC (buf, ILL_namebufsize, char);
+ ILL_SAFE_MALLOC (*names, nnames, char *);
+
+ for (i = 0; i < nnames; i++)
+ {
+ (*names)[i] = (char *) NULL;
+ }
+
+ for (i = 0; i < nnames; i++)
+ {
+ sprintf (buf, "%c%d", prefix, i);
+ len = strlen (buf) + 1;
+ ILL_SAFE_MALLOC ((*names)[i], len, char);
+
+ strcpy ((*names)[i], buf);
+ }
+
+CLEANUP:
+
+ if (rval)
+ {
+ if (*names)
+ {
+ ILLfree_names (*names, nnames);
+ *names = (char **) NULL;
+ }
+ }
+
+ ILL_IFFREE (buf, char);
+
+ if (rval)
+ {
+ QSlog("ILLsymboltab_generate_names failed");
+ }
+ return rval;
+}
diff --git a/qsopt_ex/names.h b/qsopt_ex/names.h
new file mode 100644
index 0000000..d065f7b
--- /dev/null
+++ b/qsopt_ex/names.h
@@ -0,0 +1,35 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCSINFO $Id: names.h,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+#ifndef ILL_NAMES_H
+#define ILL_NAMES_H
+
+extern void ILLfree_names (
+ char **names,
+ int count);
+extern int ILLgenerate_names (
+ char prefix,
+ int nnames,
+ char ***names);
+
+#endif
diff --git a/qsopt_ex/presolve.c b/qsopt_ex/presolve.c
new file mode 100644
index 0000000..6b9e06e
--- /dev/null
+++ b/qsopt_ex/presolve.c
@@ -0,0 +1,2634 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: presolve.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+static int TRACE = 0;
+
+/****************************************************************************/
+/* */
+/* Presolve Routine for Simplex Method */
+/* */
+/* EXPORTED FUNCTIONS */
+/* */
+/* int EGLPNUM_TYPENAME_ILLlp_add_logicals (ILLlpata *lp) */
+/* int EGLPNUM_TYPENAME_ILLlp_presolve (EGLPNUM_TYPENAME_ILLlpdata *lp) */
+/* int EGLPNUM_TYPENAME_ILLlp_scale (EGLPNUM_TYPENAME_ILLlpdata *lp) */
+/* void EGLPNUM_TYPENAME_ILLlp_sinfo_init (EGLPNUM_TYPENAME_ILLlp_sinfo *sinfo) */
+/* void EGLPNUM_TYPENAME_ILLlp_sinfo_free (EGLPNUM_TYPENAME_ILLlp_sinfo *sinfo) */
+/* void EGLPNUM_TYPENAME_ILLlp_predata_init (EGLPNUM_TYPENAME_ILLlp_predata *pre) */
+/* void EGLPNUM_TYPENAME_ILLlp_predata_free (EGLPNUM_TYPENAME_ILLlp_predata *pre) */
+/* */
+/* NOTES */
+/* */
+/* presolve will assume that logicals have been added. */
+/* */
+/****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "presolve_EGLPNUM_TYPENAME.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "allocrus.h"
+#include "eg_lpnum.h"
+#include "eg_io.h"
+#include "except.h"
+#include "zeit.h"
+
+#include "lpdata_EGLPNUM_TYPENAME.h"
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+//extern EGLPNUM_TYPE EGLPNUM_TYPENAME_SZERO_TOLER;
+
+#define ILL_LP_STATUS_OK (0)
+#define ILL_PRE_FEAS_TOL EGLPNUM_TYPENAME_PFEAS_TOLER //(1e-6)
+#define ILL_PRE_ZERO_TOL EGLPNUM_TYPENAME_PIVOT_TOLER //(1e-10)
+
+#define ILL_PRE_DELETE_EMPTY_ROW (1)
+#define ILL_PRE_DELETE_SINGLETON_ROW (2)
+#define ILL_PRE_DELETE_FIXED_VARIABLE (3)
+#define ILL_PRE_DELETE_FORCED_VARIABLE (4)
+#define ILL_PRE_DELETE_SINGLETON_VARIABLE (5)
+#define ILL_PRE_DELETE_FREE_SINGLETON_VARIABLE (6)
+#define ILL_PRE_DELETE_EMPTY_COLUMN (7)
+
+#define ILL_PRE_COL_STRUC (0)
+#define ILL_PRE_COL_LOGICAL (1)
+
+static int debug = 0;
+
+typedef struct
+{
+ int row;
+ int col;
+ char coltype;
+ char mark;
+ char del;
+ EGLPNUM_TYPE coef;
+}
+edge;
+
+typedef struct node
+{
+ edge **adj;
+ EGLPNUM_TYPE obj;
+ EGLPNUM_TYPE lower;
+ EGLPNUM_TYPE upper;
+ EGLPNUM_TYPE rhs;
+ int deg;
+ char mark;
+ char del;
+ char coltype;
+ char rowsense;
+}
+node;
+
+typedef struct intptr
+{
+ int this_val;
+ struct intptr *next;
+}
+intptr;
+
+typedef struct graph
+{
+ edge *edgelist;
+ struct node *rows;
+ struct node *cols;
+ int ecount;
+ int nrows;
+ int ncols;
+ int nzcount;
+ edge **adjspace;
+ ILLptrworld intptrworld;
+ int objsense;
+}
+graph;
+
+static void set_fixed_variable (
+ graph * G,
+ int j,
+ EGLPNUM_TYPE val),
+ get_implied_rhs_bounds (
+ graph * G,
+ int i,
+ EGLPNUM_TYPE * lb,
+ EGLPNUM_TYPE * ub),
+ get_implied_variable_bounds (
+ graph * G,
+ int j,
+ edge * a_ij,
+ EGLPNUM_TYPE * lb,
+ EGLPNUM_TYPE * ub),
+ dump_line (
+ EGLPNUM_TYPENAME_ILLlp_preline * line),
+ init_graph (
+ graph * G),
+ free_graph (
+ graph * G),
+ dump_graph (
+ graph * G);
+
+static int simple_presolve (
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ EGLPNUM_TYPENAME_ILLlp_predata * pre,
+ EGLPNUM_TYPENAME_ILLlp_sinfo * info,
+ int pre_types,
+ int *status),
+ grab_lp_line (
+ graph * G,
+ int indx,
+ EGLPNUM_TYPENAME_ILLlp_preline * line,
+ int row_or_col),
+ grab_lp_info (
+ graph * G,
+ char **colnames,
+ EGLPNUM_TYPENAME_ILLlp_sinfo * info),
+ fixed_variables (
+ graph * G,
+ EGLPNUM_TYPENAME_ILLlp_predata * pre),
+ empty_columns (
+ graph * G,
+ EGLPNUM_TYPENAME_ILLlp_predata * pre),
+ singleton_rows (
+ graph * G,
+ EGLPNUM_TYPENAME_ILLlp_predata * pre,
+ int *hit),
+ forcing_constraints (
+ graph * G,
+ EGLPNUM_TYPENAME_ILLlp_predata * pre,
+ int *hit),
+ singleton_columns (
+ graph * G,
+ EGLPNUM_TYPENAME_ILLlp_predata * pre,
+ int *hit),
+ duplicate_rows (
+ graph * G,
+ int *hit),
+ duplicate_cols (
+ graph * G,
+ int *hit),
+ gather_dup_lists (
+ int *s,
+ int count,
+ int *duptotal,
+ int **dupcnt,
+ int **dupind),
+ get_next_preop (
+ EGLPNUM_TYPENAME_ILLlp_predata * pre,
+ EGLPNUM_TYPENAME_ILLlp_preop ** op),
+ add_to_list (
+ ILLptrworld * world,
+ intptr ** list,
+ int i),
+ build_graph (
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ graph * G);
+
+
+ILL_PTRWORLD_ROUTINES (intptr, intptralloc, intptr_bulkalloc, intptrfree)
+ILL_PTRWORLD_LISTFREE_ROUTINE (intptr, intptr_listfree, intptrfree)
+ILL_PTRWORLD_LEAKS_ROUTINE (intptr, intptr_check_leaks, this_val, int)
+ int EGLPNUM_TYPENAME_ILLlp_add_logicals (
+ EGLPNUM_TYPENAME_ILLlpdata * lp)
+{
+ int rval = 0;
+ int ncols, nrows, nzcount, i, aindex;
+ char *sense;
+ EGLPNUM_TYPENAME_ILLmatrix *A;
+
+ if (!lp)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlp_add_logicals called with a NULL pointer");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ QSlog("EGLPNUM_TYPENAME_ILLlp_add_logicals ...");
+
+ A = &lp->A;
+ sense = lp->sense;
+ ncols = lp->ncols;
+ nrows = lp->nrows;
+ nzcount = lp->nzcount;
+
+ if (nrows == 0)
+ goto CLEANUP;
+ EGLPNUM_TYPENAME_EGlpNumReallocArray (&(lp->obj), lp->colsize + nrows);
+ EGLPNUM_TYPENAME_EGlpNumReallocArray (&(lp->upper), lp->colsize + nrows);
+ EGLPNUM_TYPENAME_EGlpNumReallocArray (&(lp->lower), lp->colsize + nrows);
+ lp->colnames =
+ EGrealloc (lp->colnames, sizeof (char *) * (lp->colsize + nrows));
+ //rval = ILLutil_reallocrus_count ((void **) &(lp->colnames),
+ // lp->colsize + nrows, sizeof (char *));
+ //ILL_CLEANUP_IF (rval);
+ memset (lp->colnames + ncols, 0, sizeof (char *) * nrows);
+
+ ILL_SAFE_MALLOC (lp->rowmap, lp->rowsize, int);
+
+
+ A->matcnt = EGrealloc (A->matcnt, sizeof (int) * (A->matcolsize + nrows));
+ //rval = ILLutil_reallocrus_count ((void **) &(A->matcnt),
+ // A->matcolsize + nrows, sizeof (int));
+ //ILL_CLEANUP_IF (rval);
+
+ A->matbeg = EGrealloc (A->matbeg, sizeof (int) * (A->matcolsize + nrows));
+ //rval = ILLutil_reallocrus_count ((void **) &(A->matbeg),
+ // A->matcolsize + nrows, sizeof (int));
+ //ILL_CLEANUP_IF (rval);
+
+ A->matind = EGrealloc (A->matind, sizeof (int) * (A->matsize + nrows));
+ //rval = ILLutil_reallocrus_count ((void **) &(A->matind),
+ // A->matsize + nrows, sizeof (int));
+ //ILL_CLEANUP_IF (rval);
+ EGLPNUM_TYPENAME_EGlpNumReallocArray (&(A->matval), A->matsize + nrows);
+
+ for (i = 0; i < nrows; i++)
+ {
+ A->matind[A->matsize + i] = -1;
+ }
+
+ aindex = A->matsize - A->matfree;
+
+ for (i = 0; i < nrows; i++)
+ {
+ lp->rowmap[i] = ncols;
+ EGLPNUM_TYPENAME_EGlpNumZero (lp->obj[ncols]);
+ A->matcnt[ncols] = 1;
+ A->matbeg[ncols] = aindex;
+ A->matind[aindex] = i;
+ switch (sense[i])
+ {
+ case 'E': /* Arificial */
+ EGLPNUM_TYPENAME_EGlpNumZero (lp->lower[ncols]);
+ EGLPNUM_TYPENAME_EGlpNumZero (lp->upper[ncols]);
+ EGLPNUM_TYPENAME_EGlpNumOne (A->matval[aindex]);
+ break;
+ case 'G': /* Surplus */
+ EGLPNUM_TYPENAME_EGlpNumZero (lp->lower[ncols]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->upper[ncols], EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+ EGLPNUM_TYPENAME_EGlpNumOne (A->matval[aindex]);
+ EGLPNUM_TYPENAME_EGlpNumSign (A->matval[aindex]);
+ break;
+ case 'L': /* Slack */
+ EGLPNUM_TYPENAME_EGlpNumZero (lp->lower[ncols]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->upper[ncols], EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+ EGLPNUM_TYPENAME_EGlpNumOne (A->matval[aindex]);
+ break;
+ case 'R': /* Range */
+ EGLPNUM_TYPENAME_EGlpNumZero (lp->lower[ncols]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->upper[ncols], lp->rangeval[i]);
+ EGLPNUM_TYPENAME_EGlpNumOne (A->matval[aindex]);
+ EGLPNUM_TYPENAME_EGlpNumSign (A->matval[aindex]);
+ break;
+ default:
+ QSlog("unknown sense %c in EGLPNUM_TYPENAME_ILLlp_add_logicals", sense[i]);
+ rval = 1;
+ goto CLEANUP;
+ }
+ ncols++;
+ nzcount++;
+ aindex++;
+ }
+
+ lp->ncols = ncols;
+ lp->nzcount = nzcount;
+ A->matcols = ncols;
+
+ lp->colsize += nrows;
+ A->matsize += nrows;
+ A->matcolsize += nrows;
+
+ if (lp->rA)
+ {
+ EGLPNUM_TYPENAME_ILLlp_rows_clear (lp->rA);
+ }
+ else
+ {
+ ILL_SAFE_MALLOC (lp->rA, 1, EGLPNUM_TYPENAME_ILLlp_rows);
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLlp_rows_init (lp->rA, lp, 1);
+ ILL_CLEANUP_IF (rval);
+
+CLEANUP:
+
+ ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLlp_add_logicals");
+}
+
+int EGLPNUM_TYPENAME_ILLlp_scale (
+ EGLPNUM_TYPENAME_ILLlpdata * lp)
+{
+ int rval = 0;
+ int i, j, k, col, row, nstruct, start, stop;
+ EGLPNUM_TYPENAME_ILLmatrix *A;
+ EGLPNUM_TYPE rho;
+ EGLPNUM_TYPE *gama = 0;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (rho);
+
+ /* Columns - divide by largest absolute value */
+
+ if (!lp)
+ {
+ ILL_ERROR (rval, "EGLPNUM_TYPENAME_ILLlp_scale called with a NULL pointer");
+ }
+
+ if (lp->nrows == 0 || lp->ncols == 0)
+ goto CLEANUP;
+
+ A = &lp->A;
+ nstruct = lp->nstruct;
+
+ for (j = 0; j < nstruct; j++)
+ {
+ col = lp->structmap[j];
+ EGLPNUM_TYPENAME_EGlpNumZero (rho);
+
+ start = A->matbeg[col];
+ stop = start + A->matcnt[col];
+
+ for (k = start; k < stop; k++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (rho, A->matval[k]);
+ }
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (rho))
+ {
+ for (k = start; k < stop; k++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumDivTo (A->matval[k], rho);
+ }
+ EGLPNUM_TYPENAME_EGlpNumDivTo (lp->obj[col], rho);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (lp->lower[col], EGLPNUM_TYPENAME_ILL_MINDOUBLE))
+ EGLPNUM_TYPENAME_EGlpNumMultTo (lp->lower[col], rho);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (lp->upper[col], EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+ EGLPNUM_TYPENAME_EGlpNumMultTo (lp->upper[col], rho);
+ }
+ }
+
+ gama = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+ for (i = 0; i < lp->nrows; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumZero (gama[i]);
+ }
+
+ for (j = 0; j < nstruct; j++)
+ {
+ col = lp->structmap[j];
+ start = A->matbeg[col];
+ stop = start + A->matcnt[col];
+
+ for (k = start; k < stop; k++)
+ {
+ row = A->matind[k];
+ EGLPNUM_TYPENAME_EGlpNumSetToMaxAbs (gama[row], A->matval[k]);
+ }
+ }
+
+ for (j = 0; j < nstruct; j++)
+ {
+ col = lp->structmap[j];
+ start = A->matbeg[col];
+ stop = start + A->matcnt[col];
+
+ for (k = start; k < stop; k++)
+ {
+ row = A->matind[k];
+ if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (gama[row]))
+ {
+ EGLPNUM_TYPENAME_EGlpNumDivTo (A->matval[k], gama[row]);
+ }
+ }
+ }
+
+ for (i = 0; i < lp->nrows; i++)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero ( gama[i]))
+ {
+ EGLPNUM_TYPENAME_EGlpNumDivTo (lp->rhs[i], gama[i]);
+ col = lp->rowmap[i];
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (lp->upper[col], EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+ {
+ EGLPNUM_TYPENAME_EGlpNumDivTo (lp->upper[col], gama[i]); /* Ranged row */
+ }
+ }
+ }
+
+ if (lp->rA)
+ { /* Need to clear the row version of data */
+ EGLPNUM_TYPENAME_ILLlp_rows_clear (lp->rA);
+ ILL_IFFREE (lp->rA, EGLPNUM_TYPENAME_ILLlp_rows);
+ }
+
+
+CLEANUP:
+
+ EGLPNUM_TYPENAME_EGlpNumClearVar (rho);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (gama);
+ ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLlp_scale");
+}
+
+int EGLPNUM_TYPENAME_ILLlp_presolve (
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ int pre_types)
+{
+ int rval = 0;
+ int status = ILL_LP_STATUS_OK;
+ EGLPNUM_TYPENAME_ILLlp_predata *pre = 0;
+ EGLPNUM_TYPENAME_ILLlp_sinfo *info = 0;
+
+ if (!lp)
+ {
+ QSlog("EGLPNUM_TYPENAME_ILLlp_presolve called with a NULL pointer");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+
+/*
+ ILLlpdata_writelp (lp, 0);
+*/
+
+ ILL_SAFE_MALLOC (pre, 1, EGLPNUM_TYPENAME_ILLlp_predata);
+ EGLPNUM_TYPENAME_ILLlp_predata_init (pre);
+
+ ILL_SAFE_MALLOC (info, 1, EGLPNUM_TYPENAME_ILLlp_sinfo);
+ EGLPNUM_TYPENAME_ILLlp_sinfo_init (info);
+
+ rval = simple_presolve (lp, pre, info, pre_types, &status);
+ ILL_CLEANUP_IF (rval);
+ if (status != ILL_LP_STATUS_OK)
+ {
+ QSlog("simple_presolve returned with bad status");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+/*
+ rval = EGLPNUM_TYPENAME_ILLlp_sinfo_print (info);
+ ILL_CLEANUP_IF (rval);
+*/
+
+CLEANUP:
+
+ if (rval)
+ {
+ if (pre)
+ {
+ EGLPNUM_TYPENAME_ILLlp_predata_free (pre);
+ ILL_IFFREE (pre, EGLPNUM_TYPENAME_ILLlp_predata);
+ }
+
+ if (info)
+ {
+ EGLPNUM_TYPENAME_ILLlp_sinfo_free (info);
+ ILL_IFFREE (info, EGLPNUM_TYPENAME_ILLlp_sinfo);
+ }
+ }
+ else
+ {
+ lp->presolve = pre;
+ lp->sinfo = info;
+ }
+
+ ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLlp_presolve");
+}
+
+
+#if 0
+int ILLlp_presolve_addrow (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int cnt,
+ int *ind,
+ double *val,
+ double rhs)
+{
+ int rval = 0;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp;
+ EGLPNUM_TYPENAME_ILLlp_sinfo *S;
+ EGLPNUM_TYPENAME_ILLmatrix *A;
+
+ /* This will need to evolve into a function that handles the task */
+ /* of working through the presolve data to determine the new LP */
+ /* created when a row is added to the original LP. */
+
+ /* The copies of the obj and bound used in the simplex code are */
+ /* also updated in this function. */
+
+ if (!lp)
+ {
+ QSlog("ILLlp_presolve_addrow is called without an LP");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ if (lp->presolve != 0)
+ {
+ QSlog("Not yet set up to handle addrows after presolve");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ qslp = lp->O;
+ S = qslp->sinfo;
+ A = S->A;
+
+
+ rval = ILLlib_matrix_addrow (A, cnt, ind, val, rhs);
+ ILL_CLEANUP_IF (rval);
+
+
+CLEANUP:
+
+ ILL_RETURN (rval, "ILLlp_presolve_addrow");
+}
+#endif
+
+
+static int simple_presolve (
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ EGLPNUM_TYPENAME_ILLlp_predata * pre,
+ EGLPNUM_TYPENAME_ILLlp_sinfo * info,
+ int pre_types,
+ int *status)
+{
+ int rval = 0;
+ int i, hit, newhit;
+ graph G;
+
+ if (status)
+ *status = ILL_LP_STATUS_OK;
+ init_graph (&G);
+
+ if (!lp)
+ {
+ QSlog("simple_presolve called with a NULL pointer");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ QSlog("Initial Rows = %d, Cols = %d, Nzcount = %d",
+ lp->nrows, lp->ncols, lp->nzcount);
+
+ rval = build_graph (lp, &G);
+ ILL_CLEANUP_IF (rval);
+ if (debug)
+ dump_graph (&G);
+
+ if (pre_types & EGLPNUM_TYPENAME_ILL_PRE_FIXED)
+ {
+ rval = fixed_variables (&G, pre);
+ ILL_CLEANUP_IF (rval);
+ }
+
+ do
+ {
+ hit = 0;
+ if (pre_types & EGLPNUM_TYPENAME_ILL_PRE_SINGLE_ROW)
+ {
+ rval = singleton_rows (&G, pre, &newhit);
+ ILL_CLEANUP_IF (rval);
+ hit += newhit;
+ }
+
+ if (pre_types & EGLPNUM_TYPENAME_ILL_PRE_FORCING)
+ {
+ rval = forcing_constraints (&G, pre, &newhit);
+ ILL_CLEANUP_IF (rval);
+ hit += newhit;
+ }
+
+ if (pre_types & EGLPNUM_TYPENAME_ILL_PRE_SINGLE_COL)
+ {
+ rval = singleton_columns (&G, pre, &newhit);
+ ILL_CLEANUP_IF (rval);
+ hit += newhit;
+ }
+
+ if (pre_types & EGLPNUM_TYPENAME_ILL_PRE_DUPLICATE_ROW)
+ {
+ rval = duplicate_rows (&G, &newhit);
+ ILL_CLEANUP_IF (rval);
+ hit += newhit;
+ }
+
+ if (pre_types & EGLPNUM_TYPENAME_ILL_PRE_DUPLICATE_COL)
+ {
+ rval = duplicate_cols (&G, &newhit);
+ ILL_CLEANUP_IF (rval);
+ hit += newhit;
+ }
+
+
+/*
+ {
+ int k, cnt = 0;
+ for (i = 0; i < G.ncols; i++) {
+ if (G.cols[i].del == 0) {
+ for (k = 0; k < G.cols[i].deg; k++) {
+ if (G.cols[i].adj[k]->del == 0) {
+ cnt++;
+ }
+ }
+ }
+ }
+ QSlog("Current NZCOUNT = %d", cnt);
+ }
+*/
+ } while (hit);
+
+ if (EGLPNUM_TYPENAME_ILL_PRE_EMPTY_COL)
+ {
+ rval = empty_columns (&G, pre);
+ ILL_CLEANUP_IF (rval);
+ }
+
+ if (debug)
+ {
+ QSlog("Operations");
+ for (i = 0; i < pre->opcount; i++)
+ {
+ switch (pre->oplist[i].ptype)
+ {
+ case ILL_PRE_DELETE_EMPTY_ROW:
+ QSlog("Delete Empty Row: %d", pre->oplist[i].rowindex);
+ break;
+ case ILL_PRE_DELETE_SINGLETON_ROW:
+ QSlog("Delete Singleton Row: %d (col %d)",
+ pre->oplist[i].rowindex, pre->oplist[i].colindex);
+ dump_line (&pre->oplist[i].line);
+ break;
+ case ILL_PRE_DELETE_FIXED_VARIABLE:
+ QSlog("Delete Fixed Variable: %d", pre->oplist[i].colindex);
+ dump_line (&pre->oplist[i].line);
+ break;
+ case ILL_PRE_DELETE_FORCED_VARIABLE:
+ QSlog("Delete Forced Variable: %d", pre->oplist[i].colindex);
+ dump_line (&pre->oplist[i].line);
+ break;
+ case ILL_PRE_DELETE_SINGLETON_VARIABLE:
+ QSlog("Delete Singleton Variable: %d", pre->oplist[i].colindex);
+ dump_line (&pre->oplist[i].line);
+ break;
+ case ILL_PRE_DELETE_FREE_SINGLETON_VARIABLE:
+ QSlog("Delete Free Singleton Variable: %d",
+ pre->oplist[i].colindex);
+ dump_line (&pre->oplist[i].line);
+ break;
+ case ILL_PRE_DELETE_EMPTY_COLUMN:
+ QSlog("Delete Empty Column: %d", pre->oplist[i].colindex);
+ dump_line (&pre->oplist[i].line);
+ break;
+ default:
+ QSlog("unknon presolve operation");
+ rval = 1;
+ goto CLEANUP;
+ }
+ }
+ }
+
+ rval = grab_lp_info (&G, lp->colnames, info);
+ ILL_CLEANUP_IF (rval);
+
+/*
+ QSlog("Final Rows = %d, Cols = %d, Nzcount = %d",
+ info->nrows, info->ncols, info->nzcount);
+*/
+
+
+CLEANUP:
+
+ free_graph (&G);
+ ILL_RETURN (rval, "simple_presolve");
+}
+
+static int grab_lp_line (
+ graph * G,
+ int indx,
+ EGLPNUM_TYPENAME_ILLlp_preline * line,
+ int row_or_col)
+{
+ int rval = 0;
+ int k, cnt;
+ node *n;
+
+ if (row_or_col == 0)
+ n = &G->rows[indx];
+ else
+ n = &G->cols[indx];
+
+ line->count = 0;
+
+ for (k = 0; k < n->deg; k++)
+ {
+ if (n->adj[k]->del == 0)
+ {
+ line->count++;
+ }
+ }
+
+ if (line->count)
+ {
+ ILL_SAFE_MALLOC (line->ind, line->count, int);
+
+ line->val = EGLPNUM_TYPENAME_EGlpNumAllocArray (line->count);
+ if (!line->ind || !line->val)
+ {
+ QSlog("out of memory in grab_lp_line");
+ rval = 1;
+ goto CLEANUP;
+ }
+ for (k = 0, cnt = 0; k < n->deg; k++)
+ {
+ if (n->adj[k]->del == 0)
+ {
+ line->ind[cnt] = n->adj[k]->row;
+ EGLPNUM_TYPENAME_EGlpNumCopy (line->val[cnt], n->adj[k]->coef);
+ cnt++;
+ }
+ }
+ }
+
+ if (row_or_col == 0)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (line->rhs, n->rhs);
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (line->obj, n->obj);
+ EGLPNUM_TYPENAME_EGlpNumCopy (line->lower, n->lower);
+ EGLPNUM_TYPENAME_EGlpNumCopy (line->upper, n->upper);
+ }
+
+ line->row_or_col = row_or_col;
+
+CLEANUP:
+
+ ILL_RETURN (rval, "grab_lp_line");
+}
+
+static void dump_line (
+ EGLPNUM_TYPENAME_ILLlp_preline * line)
+{
+ int k;
+
+ if (line->row_or_col == 0)
+ {
+ for (k = 0; k < line->count; k++)
+ {
+ QSlog(" C%d->%g", line->ind[k], EGLPNUM_TYPENAME_EGlpNumToLf (line->val[k]));
+ }
+ QSlog(" RHS->%g", EGLPNUM_TYPENAME_EGlpNumToLf (line->rhs));
+ }
+ else
+ {
+ for (k = 0; k < line->count; k++)
+ {
+ QSlog(" R%d->%g", line->ind[k], EGLPNUM_TYPENAME_EGlpNumToLf (line->val[k]));
+ }
+ QSlog(" Obj->%g LB->%g UB->%g", EGLPNUM_TYPENAME_EGlpNumToLf (line->obj),
+ EGLPNUM_TYPENAME_EGlpNumToLf (line->lower), EGLPNUM_TYPENAME_EGlpNumToLf (line->upper));
+ }
+}
+
+static int grab_lp_info (
+ graph * G,
+ char **colnames,
+ EGLPNUM_TYPENAME_ILLlp_sinfo * info)
+{
+ int rval = 0;
+ int ncols = 0, nrows = 0, nzcount = 0;
+ int i, j, k, cnt, len;
+ node *grows = G->rows;
+ node *gcols = G->cols;
+ int *tdeg = 0;
+ int *map = 0;
+ char *buf = 0;
+ EGLPNUM_TYPENAME_ILLmatrix *A = &info->A;
+
+ ILL_SAFE_MALLOC (tdeg, G->ncols, int);
+ ILL_SAFE_MALLOC (map, G->nrows, int);
+
+ if (!tdeg || !map)
+ {
+ QSlog("out of memory in grab_lp_info");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ for (i = 0; i < G->nrows; i++)
+ {
+ if (grows[i].del == 0)
+ {
+ map[i] = nrows;
+ nrows++;
+ }
+ }
+
+ for (j = 0; j < G->ncols; j++)
+ {
+ if (gcols[j].del == 0)
+ {
+ tdeg[ncols] = 0;
+ for (k = 0; k < gcols[j].deg; k++)
+ {
+ if (gcols[j].adj[k]->del == 0)
+ {
+ tdeg[ncols]++;
+ nzcount++;
+ }
+ }
+ ncols++;
+ }
+ }
+
+ info->ncols = ncols;
+ info->nrows = nrows;
+ info->nzcount = nzcount;
+
+ info->rowsize = nrows;
+ info->colsize = ncols;
+
+ info->rhs = EGLPNUM_TYPENAME_EGlpNumAllocArray (nrows);
+ info->obj = EGLPNUM_TYPENAME_EGlpNumAllocArray (ncols);
+ info->upper = EGLPNUM_TYPENAME_EGlpNumAllocArray (ncols);
+ info->lower = EGLPNUM_TYPENAME_EGlpNumAllocArray (ncols);
+ A->matval = EGLPNUM_TYPENAME_EGlpNumAllocArray (info->nzcount + 1);
+ ILL_SAFE_MALLOC (A->matind, info->nzcount + 1, int);
+ ILL_SAFE_MALLOC (A->matcnt, info->colsize, int);
+ ILL_SAFE_MALLOC (A->matbeg, info->colsize, int);
+
+ if (!info->rhs || !info->obj || !info->lower || !info->upper ||
+ !A->matval || !A->matind || !A->matcnt || !A->matbeg)
+ {
+ QSlog("out of memory in grab_lp");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ A->matind[info->nzcount] = -1;
+ A->matsize = info->nzcount + 1;
+ A->matcolsize = info->colsize;
+ A->matfree = 1;
+ A->matcols = ncols;
+ A->matrows = nrows;
+
+
+ nrows = 0;
+ for (i = 0; i < G->nrows; i++)
+ {
+ if (grows[i].del == 0)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (info->rhs[nrows], grows[i].rhs);
+ nrows++;
+ }
+ }
+
+ ncols = 0;
+ cnt = 0;
+ for (j = 0; j < G->ncols; j++)
+ {
+ if (gcols[j].del == 0)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (info->obj[ncols], gcols[j].obj);
+ EGLPNUM_TYPENAME_EGlpNumCopy (info->lower[ncols], gcols[j].lower);
+ EGLPNUM_TYPENAME_EGlpNumCopy (info->upper[ncols], gcols[j].upper);
+ A->matcnt[ncols] = tdeg[ncols];
+ A->matbeg[ncols] = cnt;
+ for (k = 0; k < gcols[j].deg; k++)
+ {
+ if (gcols[j].adj[k]->del == 0)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (A->matval[cnt], gcols[j].adj[k]->coef);
+ A->matind[cnt] = map[gcols[j].adj[k]->row];
+ cnt++;
+ }
+ }
+ ncols++;
+ }
+ }
+
+ if (colnames)
+ {
+ ILL_SAFE_MALLOC (info->colnames, info->colsize, char *);
+
+ if (!info->colnames)
+ {
+ QSlog("out of memory in grab_lp");
+ rval = 1;
+ goto CLEANUP;
+ }
+ for (j = 0; j < info->colsize; j++)
+ {
+ info->colnames[j] = 0;
+ }
+
+ ILL_SAFE_MALLOC (buf, ILL_namebufsize, char);
+
+ if (!buf)
+ {
+ QSlog("out of memory in grab_lp");
+ rval = 1;
+ goto CLEANUP;
+ }
+ ncols = 0;
+ for (j = 0; j < G->ncols; j++)
+ {
+ if (gcols[j].del == 0)
+ {
+ if (gcols[j].coltype == ILL_PRE_COL_STRUC)
+ {
+ len = strlen (colnames[j]) + 1;
+ ILL_SAFE_MALLOC (info->colnames[ncols], len, char);
+
+ if (!info->colnames[ncols])
+ {
+ QSlog("out of memory in grab_lp");
+ rval = 1;
+ goto CLEANUP;
+ }
+ strcpy (info->colnames[ncols], colnames[j]);
+ }
+ else
+ {
+ for (k = 0; k < gcols[j].deg; k++)
+ {
+ if (gcols[j].adj[k]->del == 0)
+ {
+ i = gcols[j].adj[k]->row;
+ break;
+ }
+ }
+ if (k == gcols[j].deg)
+ {
+ QSlog("problem with graph in grab_lp");
+ rval = 1;
+ goto CLEANUP;
+ }
+ sprintf (buf, "s%d", i);
+ len = strlen (buf) + 1;
+ ILL_SAFE_MALLOC (info->colnames[ncols], len, char);
+
+ if (!info->colnames[ncols])
+ {
+ QSlog("out of memory in grab_lp");
+ rval = 1;
+ goto CLEANUP;
+ }
+ strcpy (info->colnames[ncols], buf);
+ }
+ ncols++;
+ }
+ }
+ }
+
+/* ADD STRUCT VARIABLE STUFF */
+
+
+CLEANUP:
+
+ if (rval)
+ {
+ EGLPNUM_TYPENAME_ILLlp_sinfo_free (info);
+ }
+ ILL_IFFREE (tdeg, int);
+ ILL_IFFREE (map, int);
+ ILL_IFFREE (buf, char);
+
+ ILL_RETURN (rval, "grab_lp_info");
+}
+
+static int fixed_variables (
+ graph * G,
+ EGLPNUM_TYPENAME_ILLlp_predata * pre)
+{
+ int rval = 0;
+ int j;
+ int ncols = G->ncols;
+ node *cols = G->cols;
+ EGLPNUM_TYPENAME_ILLlp_preop *op = 0;
+
+ for (j = 0; j < ncols; j++)
+ {
+ if (cols[j].del == 0)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (cols[j].lower, cols[j].upper))
+ {
+ rval = get_next_preop (pre, &op);
+ ILL_CLEANUP_IF (rval);
+
+ op->colindex = j;
+ op->rowindex = -1;
+ op->ptype = ILL_PRE_DELETE_FIXED_VARIABLE;
+
+ rval = grab_lp_line (G, op->colindex, &op->line, 1);
+ ILL_CLEANUP_IF (rval);
+ pre->opcount++;
+
+ set_fixed_variable (G, j, cols[j].lower);
+ }
+ }
+ }
+
+CLEANUP:
+
+ ILL_RETURN (rval, "fixed_variables");
+}
+
+static int empty_columns (
+ graph * G,
+ EGLPNUM_TYPENAME_ILLlp_predata * pre)
+{
+ int rval = 0;
+ int j, k;
+ int ncols = G->ncols;
+ node *cols = G->cols;
+ EGLPNUM_TYPENAME_ILLlp_preop *op = 0;
+ EGLPNUM_TYPE objtmp;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (objtmp);
+
+ for (j = 0; j < ncols; j++)
+ {
+ if (cols[j].del == 0)
+ {
+ for (k = 0; k < cols[j].deg; k++)
+ {
+ if (cols[j].adj[k]->del == 0)
+ break;
+ }
+ if (k == cols[j].deg)
+ {
+ rval = get_next_preop (pre, &op);
+ ILL_CLEANUP_IF (rval);
+
+ op->colindex = j;
+ op->rowindex = -1;
+ op->ptype = ILL_PRE_DELETE_EMPTY_COLUMN;
+
+ rval = grab_lp_line (G, op->colindex, &op->line, 1);
+ ILL_CLEANUP_IF (rval);
+ pre->opcount++;
+ EGLPNUM_TYPENAME_EGlpNumCopy (objtmp, cols[j].obj);
+ if (G->objsense < 0)
+ EGLPNUM_TYPENAME_EGlpNumSign (objtmp);
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (objtmp, ILL_PRE_FEAS_TOL))
+ {
+ set_fixed_variable (G, j, cols[j].lower);
+ }
+ else if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (objtmp))
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (cols[j].lower, EGLPNUM_TYPENAME_ILL_MINDOUBLE))
+ {
+ QSlog("unbounded prob detected in empty_columns");
+ QSlog("col %d, obj %g", j, EGLPNUM_TYPENAME_EGlpNumToLf (cols[j].obj));
+ rval = 1;
+ goto CLEANUP;
+ }
+ else
+ {
+ set_fixed_variable (G, j, cols[j].lower);
+ }
+ }
+ else if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (objtmp))
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (cols[j].upper, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+ {
+ QSlog("unbounded prob detected in empty_columns");
+ QSlog("col %d, obj %g", j, EGLPNUM_TYPENAME_EGlpNumToLf (cols[j].obj));
+ rval = 1;
+ goto CLEANUP;
+ }
+ else
+ {
+ set_fixed_variable (G, j, cols[j].upper);
+ }
+ }
+ else
+ {
+ set_fixed_variable (G, j, cols[j].lower);
+ }
+ }
+ }
+ }
+
+CLEANUP:
+
+ EGLPNUM_TYPENAME_EGlpNumClearVar (objtmp);
+ ILL_RETURN (rval, "empty_columns");
+}
+
+static int singleton_rows (
+ graph * G,
+ EGLPNUM_TYPENAME_ILLlp_predata * pre,
+ int *hit)
+{
+ int rval = 0;
+ int rowindex, i, k, h;
+ int nrows = G->nrows;
+ node *rows = G->rows;
+ node *cols = G->cols;
+ node *r, *c;
+ edge *pivot, *f;
+ intptr *next, *list = 0;
+ int *tdeg = 0;
+ EGLPNUM_TYPE val;
+ EGLPNUM_TYPENAME_ILLlp_preop *op = 0;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (val);
+
+ *hit = 0;
+ if (G->nrows == 0)
+ goto CLEANUP;
+
+ ILL_SAFE_MALLOC (tdeg, G->nrows, int);
+
+ if (!tdeg)
+ {
+ QSlog("out of memory in singleton_rows");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ for (i = 0; i < nrows; i++)
+ {
+ if (rows[i].del == 0)
+ {
+ tdeg[i] = 0;
+ for (k = 0; k < rows[i].deg; k++)
+ {
+ if (rows[i].adj[k]->del == 0)
+ {
+ tdeg[i]++;
+ }
+ }
+ if (tdeg[i] <= 1)
+ {
+ rval = add_to_list (&G->intptrworld, &list, i);
+ ILL_CLEANUP_IF (rval);
+ }
+ }
+ }
+
+ while (list)
+ {
+ (*hit)++;
+ rowindex = list->this_val;
+ next = list->next;
+ intptrfree (&G->intptrworld, list);
+ list = next;
+
+ rval = get_next_preop (pre, &op);
+ ILL_CLEANUP_IF (rval);
+
+ r = &rows[rowindex];
+
+ if (tdeg[rowindex] == 0)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (r->rhs, ILL_PRE_FEAS_TOL))
+ {
+ QSlog("infeasible row detected in singleton_row");
+ QSlog("empty row with rhs = %g", EGLPNUM_TYPENAME_EGlpNumToLf (r->rhs));
+ rval = 1;
+ goto CLEANUP;
+ }
+ op->ptype = ILL_PRE_DELETE_EMPTY_ROW;
+ op->rowindex = rowindex;
+ }
+ else
+ {
+ /* Find the "pivot" entry and colum */
+
+ for (k = 0; k < r->deg; k++)
+ {
+ if (r->adj[k]->del == 0)
+ break;
+ }
+ if (k == r->deg)
+ {
+ QSlog("lost an edge in singleton_rows");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ pivot = r->adj[k];
+ c = &cols[pivot->col];
+
+ /* Store data from operation (incluing the col coefs) */
+
+ op->ptype = ILL_PRE_DELETE_SINGLETON_ROW;
+ op->rowindex = rowindex;
+ op->colindex = c - cols;
+ EGLPNUM_TYPENAME_EGlpNumCopy (op->line.rhs, r->rhs);
+ rval = grab_lp_line (G, op->colindex, &op->line, 1);
+ ILL_CLEANUP_IF (rval);
+
+ /* Fix the x[c] to its rhs value */
+ /*val = r->rhs / pivot->coef; */
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (val, r->rhs, pivot->coef);
+ /* if (val < c->lower - ILL_PRE_FEAS_TOL ||
+ * val > c->upper + ILL_PRE_FEAS_TOL) */
+ if (EGLPNUM_TYPENAME_EGlpNumIsSumLess (val, ILL_PRE_FEAS_TOL, c->lower) ||
+ EGLPNUM_TYPENAME_EGlpNumIsSumLess (c->upper, ILL_PRE_FEAS_TOL, val))
+ {
+ QSlog("infeasible bounds detected in singleton_row %d", rowindex);
+ QSlog("lower->%g upper->%g val = %g",
+ EGLPNUM_TYPENAME_EGlpNumToLf (c->lower), EGLPNUM_TYPENAME_EGlpNumToLf (c->upper),
+ EGLPNUM_TYPENAME_EGlpNumToLf (val));
+ rval = 1;
+ goto CLEANUP;
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (c->lower, val);
+ EGLPNUM_TYPENAME_EGlpNumCopy (c->upper, val);
+ }
+
+ /* Delete x[c] from other rows (and adjust their rhs) */
+
+ c->del = 1;
+
+ for (h = 0; h < c->deg; h++)
+ {
+ f = c->adj[h];
+ if (f->del == 0)
+ {
+ /*rows[f->row].rhs -= (f->coef * c->lower); */
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (rows[f->row].rhs, f->coef, c->lower);
+ tdeg[f->row]--;
+ if (tdeg[f->row] == 1)
+ {
+ if (f == pivot)
+ {
+ QSlog("bad pivot element");
+ rval = 1;
+ goto CLEANUP;
+ }
+ rval = add_to_list (&G->intptrworld, &list, f->row);
+ ILL_CLEANUP_IF (rval);
+ }
+ f->del = 1;
+ }
+ }
+ }
+
+ r->del = 1;
+ pre->opcount++;
+ }
+
+CLEANUP:
+
+ ILL_IFFREE (tdeg, int);
+
+ intptr_listfree (&G->intptrworld, list);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (val);
+ ILL_RETURN (rval, "singleton_rows");
+}
+
+static int forcing_constraints (
+ graph * G,
+ EGLPNUM_TYPENAME_ILLlp_predata * pre,
+ int *hit)
+{
+ int rval = 0;
+ int i, j, k, ts;
+ node *rows = G->rows;
+ node *cols = G->cols;
+ edge *e;
+ int nrows = G->nrows;
+ EGLPNUM_TYPE ub, lb;
+ EGLPNUM_TYPENAME_ILLlp_preop *op = 0;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (ub);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (lb);
+
+ *hit = 0;
+
+ for (i = 0; i < nrows; i++)
+ {
+ if (rows[i].del == 0)
+ {
+ get_implied_rhs_bounds (G, i, &lb, &ub);
+ if (EGLPNUM_TYPENAME_EGlpNumIsSumLess (rows[i].rhs, ILL_PRE_FEAS_TOL, lb) ||
+ EGLPNUM_TYPENAME_EGlpNumIsSumLess (ub, ILL_PRE_FEAS_TOL, rows[i].rhs))
+ {
+ QSlog("infeasible row detected in forcing_constraints");
+ QSlog("Row %d: RHS->%g LBnd->%g UBnd->%g",
+ i, EGLPNUM_TYPENAME_EGlpNumToLf (rows[i].rhs),
+ EGLPNUM_TYPENAME_EGlpNumToLf (lb), EGLPNUM_TYPENAME_EGlpNumToLf (ub));
+ rval = 1;
+ goto CLEANUP;
+ }
+ else if (EGLPNUM_TYPENAME_EGlpNumIsDiffLess (rows[i].rhs, ILL_PRE_FEAS_TOL, lb) ||
+ EGLPNUM_TYPENAME_EGlpNumIsDiffLess (ub, ILL_PRE_FEAS_TOL, rows[i].rhs))
+ {
+ (*hit)++;
+ ts = (EGLPNUM_TYPENAME_EGlpNumIsDiffLess (rows[i].rhs, ILL_PRE_FEAS_TOL, lb) ? 0 : 1);
+ for (k = 0; k < rows[i].deg; k++)
+ {
+ e = rows[i].adj[k];
+ if (e->del == 0)
+ {
+ j = e->col;
+
+ rval = get_next_preop (pre, &op);
+ ILL_CLEANUP_IF (rval);
+
+ op->colindex = j;
+ op->rowindex = i;
+ op->ptype = ILL_PRE_DELETE_FORCED_VARIABLE;
+
+ rval = grab_lp_line (G, j, &op->line, 1);
+ ILL_CLEANUP_IF (rval);
+ pre->opcount++;
+
+ if ((ts == 0 && EGLPNUM_TYPENAME_EGlpNumIsLessZero (e->coef)) ||
+ (ts == 1 && EGLPNUM_TYPENAME_EGlpNumIsGreatZero (e->coef)))
+ {
+ set_fixed_variable (G, j, cols[j].upper);
+ }
+ else
+ {
+ set_fixed_variable (G, j, cols[j].lower);
+ }
+ }
+ }
+ }
+ }
+ }
+
+CLEANUP:
+
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ub);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (lb);
+ ILL_RETURN (rval, "forcing_constraints");
+}
+
+static int singleton_columns (
+ graph * G,
+ EGLPNUM_TYPENAME_ILLlp_predata * pre,
+ int *hit)
+{
+ int rval = 0;
+ int ncols = G->ncols;
+ int j, k, deg, rdeg, single = 0, irow;
+ EGLPNUM_TYPE lb, ub, b, eb;
+ node *cols = G->cols;
+ node *rows = G->rows;
+ edge *b_edge;
+ EGLPNUM_TYPENAME_ILLlp_preop *op = 0;
+ EGLPNUM_TYPE newub, newlb;
+ EGLPNUM_TYPE a, c, l, u;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (lb);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (ub);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (eb);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (b);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (newlb);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (newub);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (a);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (c);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (l);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (u);
+
+ *hit = 0;
+ if (G->ncols == 0)
+ goto CLEANUP;
+
+ for (j = 0; j < ncols; j++)
+ {
+ if (cols[j].del == 0)
+ {
+ deg = 0;
+ for (k = 0; k < cols[j].deg && deg <= 1; k++)
+ {
+ if (cols[j].adj[k]->del == 0)
+ {
+ single = k;
+ deg++;
+ }
+ }
+ if (deg == 1)
+ {
+ irow = cols[j].adj[single]->row;
+ EGLPNUM_TYPENAME_EGlpNumCopy (b, cols[j].adj[single]->coef);
+ b_edge = cols[j].adj[single];
+
+ get_implied_variable_bounds (G, j, b_edge, &lb, &ub);
+
+ /*if (lb >= cols[j].lower && ub <= cols[j].upper) */
+ if (EGLPNUM_TYPENAME_EGlpNumIsLeq (cols[j].lower, lb) &&
+ EGLPNUM_TYPENAME_EGlpNumIsLeq (ub, cols[j].upper))
+ {
+ edge *a_edge;
+
+ /* The jth variable can be substituted out of problem */
+ /* x = (c/b) - (a/b)y */
+
+
+ rval = get_next_preop (pre, &op);
+ ILL_CLEANUP_IF (rval);
+
+ op->colindex = j;
+ op->rowindex = irow;
+ op->ptype = ILL_PRE_DELETE_FREE_SINGLETON_VARIABLE;
+
+ rval = grab_lp_line (G, irow, &op->line, 0);
+ ILL_CLEANUP_IF (rval);
+ pre->opcount++;
+
+ /* Adjust the objective function */
+ /* dy ==> (d - (e/b))ay (e is obj coef of y) */
+ /*eb = cols[j].obj / b; */
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (eb, cols[j].obj, b);
+
+ for (k = 0; k < rows[irow].deg; k++)
+ {
+ a_edge = rows[irow].adj[k];
+ if (a_edge->del == 0 && a_edge != b_edge)
+ {
+ /*cols[a_edge->col].obj -= (eb * a_edge->coef); */
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (cols[a_edge->col].obj, eb, a_edge->coef);
+ }
+ }
+
+
+ /* Delete y from graph */
+
+ cols[j].del = 1;
+
+ /* Delete equation ay + bx = c */
+
+ rows[irow].del = 1;
+ for (k = 0; k < rows[irow].deg; k++)
+ {
+ rows[irow].adj[k]->del = 1;
+ }
+
+ }
+ else
+ {
+ rdeg = 0;
+ for (k = 0; k < rows[irow].deg && rdeg <= 2; k++)
+ {
+ if (rows[irow].adj[k]->del == 0)
+ {
+ rdeg++;
+ }
+ }
+ if (rdeg == 2)
+ {
+ edge *a_edge = 0;
+ int col2 = 0;
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (newub, EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+ EGLPNUM_TYPENAME_EGlpNumCopy (newlb, EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+ EGLPNUM_TYPENAME_EGlpNumZero (a);
+
+ /* ay + bx = c */
+ /* l <= x <= u */
+ /* x - is column singleton */
+ /* derive bounds on y and substitute out x */
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (c, rows[irow].rhs);
+ EGLPNUM_TYPENAME_EGlpNumCopy (l, cols[j].lower);
+ EGLPNUM_TYPENAME_EGlpNumCopy (u, cols[j].upper);
+
+ /* Find the ay term */
+
+ for (k = 0; k < rows[irow].deg; k++)
+ {
+ if (rows[irow].adj[k]->del == 0 && rows[irow].adj[k]->col != j)
+ {
+ a_edge = rows[irow].adj[k];
+ EGLPNUM_TYPENAME_EGlpNumCopy (a, rows[irow].adj[k]->coef);
+ col2 = rows[irow].adj[k]->col;
+ break;
+ }
+ }
+ if (k == rows[irow].deg)
+ {
+ QSlog("graph error in singleton_col");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ /* Record the operation */
+ /* x is column j, y is column col2 */
+
+ rval = get_next_preop (pre, &op);
+ ILL_CLEANUP_IF (rval);
+
+ op->colindex = j;
+ op->rowindex = irow;
+ op->ptype = ILL_PRE_DELETE_SINGLETON_VARIABLE;
+
+ rval = grab_lp_line (G, irow, &op->line, 0);
+ ILL_CLEANUP_IF (rval);
+ pre->opcount++;
+
+ /* Adjust the bounds on y */
+ /* Using x = c/b - (a/b)y */
+ /* we use eb as temporal variable here */
+ /*if (a / b > 0) */
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (eb, a, b);
+ if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (eb))
+ {
+ /*if (l > -EGLPNUM_TYPENAME_ILL_MAXDOUBLE) */
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_ILL_MINDOUBLE, l))
+ {
+ /*newub = (c / a) - (l * b) / a; */
+ EGLPNUM_TYPENAME_EGlpNumCopy (newub, c);
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (newub, l, b);
+ EGLPNUM_TYPENAME_EGlpNumDivTo (newub, a);
+ }
+ /*if (u < EGLPNUM_TYPENAME_ILL_MAXDOUBLE) */
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (u, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+ {
+ /*newlb = (c / a) - (u * b) / a; */
+ EGLPNUM_TYPENAME_EGlpNumCopy (newlb, c);
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (newlb, u, b);
+ EGLPNUM_TYPENAME_EGlpNumDivTo (newlb, a);
+ }
+ }
+ else
+ {
+ /*if (l > -EGLPNUM_TYPENAME_ILL_MAXDOUBLE) */
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_ILL_MINDOUBLE, l))
+ {
+ /*newlb = (c / a) - (l * b) / a; */
+ EGLPNUM_TYPENAME_EGlpNumCopy (newlb, c);
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (newlb, l, b);
+ EGLPNUM_TYPENAME_EGlpNumDivTo (newlb, a);
+ }
+ /*if (u < EGLPNUM_TYPENAME_ILL_MAXDOUBLE) */
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (u, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+ {
+ /*newub = (c / a) - (u * b) / a; */
+ EGLPNUM_TYPENAME_EGlpNumCopy (newub, c);
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (newub, u, b);
+ EGLPNUM_TYPENAME_EGlpNumDivTo (newub, a);
+ }
+ }
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (cols[col2].lower, newlb))
+ EGLPNUM_TYPENAME_EGlpNumCopy (cols[col2].lower, newlb);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (newub, cols[col2].upper))
+ EGLPNUM_TYPENAME_EGlpNumCopy (cols[col2].upper, newub);
+ EGLPNUM_TYPENAME_EGlpNumSubTo (cols[col2].obj, eb);
+
+ /* Delete x (and the bx term) from graph */
+
+ cols[j].del = 1;
+ b_edge->del = 1;
+
+ /* Delete equation ay + bx = c (and the ax term) */
+
+ rows[irow].del = 1;
+ a_edge->del = 1;
+ }
+ }
+ }
+ }
+ }
+
+
+CLEANUP:
+
+ EGLPNUM_TYPENAME_EGlpNumClearVar (lb);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ub);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (eb);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (b);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (newlb);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (newub);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (a);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (c);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (l);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (u);
+ ILL_RETURN (rval, "singleton_columns");
+}
+
+static int duplicate_rows (
+ graph * G,
+ int *hit)
+{
+ int rval = 0;
+ node *cols = G->cols;
+ node *rows = G->rows;
+ int ncols = G->ncols;
+ int nrows = G->nrows;
+ int *s = 0;
+ EGLPNUM_TYPE *f = 0;
+ double szeit = ILLutil_zeit ();
+ EGLPNUM_TYPE q;
+ int i, j, k, k2, ri, r0 = 0, n, nu = 0, got, t0, t = 1;
+ node *c;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (q);
+
+
+ /* Code follows J. Tomlin and J. S. Welch, OR Letters 5 (1986) 7--11 */
+
+ *hit = 0;
+ if (nrows == 0)
+ goto CLEANUP;
+
+ ILL_SAFE_MALLOC (s, nrows, int);
+
+ f = EGLPNUM_TYPENAME_EGlpNumAllocArray (nrows);
+
+ for (i = 0; i < nrows; i++)
+ {
+ if (rows[i].del || rows[i].rowsense != 'E')
+ {
+ s[i] = EGLPNUM_TYPENAME_ILL_MAXINT; /* EGLPNUM_TYPENAME_ILL_MAXINT means no longer eligible */
+ }
+ else
+ {
+ s[i] = 0; /* 0 means eligible, >0 means in a group */
+ nu++; /* Tracks the number of eligible rows */
+ }
+ }
+
+ for (j = 0; j < ncols; j++)
+ {
+ c = &cols[j];
+ if (c->del)
+ continue;
+ if (c->coltype != ILL_PRE_COL_STRUC)
+ continue;
+
+ n = 0;
+ t0 = t++;
+
+ for (k = 0; k < c->deg; k++)
+ {
+ if (c->adj[k]->del)
+ continue;
+
+ ri = c->adj[k]->row;
+ if (s[ri] == 0)
+ {
+ s[ri] = t0;
+ EGLPNUM_TYPENAME_EGlpNumCopy (f[ri], c->adj[k]->coef);
+ r0 = ri;
+ n++;
+ }
+ else if (s[ri] < t0)
+ {
+ got = 0;
+ for (k2 = k + 1; k2 < c->deg; k2++)
+ {
+ if (c->adj[k2]->del)
+ continue;
+
+ i = c->adj[k2]->row;
+ if (s[i] == s[ri])
+ {
+ /*q = (c->adj[k]->coef * (f[i])) / (f[ri] * (c->adj[k2]->coef)); */
+ EGLPNUM_TYPENAME_EGlpNumCopy (q, c->adj[k]->coef);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (q, f[i]);
+ EGLPNUM_TYPENAME_EGlpNumDivTo (q, f[ri]);
+ EGLPNUM_TYPENAME_EGlpNumDivTo (q, c->adj[k2]->coef);
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqual (q, EGLPNUM_TYPENAME_oneLpNum, ILL_PRE_ZERO_TOL))
+ {
+ s[ri] = t;
+ s[i] = t;
+ got++;
+ }
+ }
+ }
+ if (got)
+ {
+ t++;
+ }
+ else
+ {
+ s[ri] = EGLPNUM_TYPENAME_ILL_MAXINT;
+ if (--nu == 0)
+ goto DONE;
+ }
+ }
+ }
+
+ if (n == 1)
+ {
+ s[r0] = EGLPNUM_TYPENAME_ILL_MAXINT;
+ if (--nu == 0)
+ goto DONE;
+ }
+ }
+
+DONE:
+
+ {
+ int idup = 0;
+
+ for (i = 0; i < nrows; i++)
+ {
+ if (s[i] > 0 && s[i] < EGLPNUM_TYPENAME_ILL_MAXINT)
+ {
+ QSlog("Row %d: %d", i, s[i]);
+ idup++;
+ }
+ }
+ QSlog("Number of duplicate rows: %d", idup);
+ }
+
+ QSlog("Time in duplicate_rows: %.2f (seconds)", ILLutil_zeit () - szeit);
+
+CLEANUP:
+
+ ILL_IFFREE (s, int);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (f);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (q);
+ ILL_RETURN (rval, "duplicate_rows");
+}
+
+static int duplicate_cols (
+ graph * G,
+ int *hit)
+{
+ int rval = 0;
+ node *cols = G->cols;
+ node *rows = G->rows;
+ int ncols = G->ncols;
+ int nrows = G->nrows;
+ int *s = 0;
+ EGLPNUM_TYPE *f = 0;
+ double szeit = ILLutil_zeit ();
+ EGLPNUM_TYPE q;
+ int i, j, k, k2, ci, c0 = 0, n, nu = 0, got, t0, t = 1;
+ node *r;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (q);
+
+
+ /* Code follows J. Tomlin and J. S. Welch, OR Letters 5 (1986) 7--11 */
+
+ *hit = 0;
+ if (ncols == 0)
+ goto CLEANUP;
+
+ ILL_SAFE_MALLOC (s, ncols, int);
+
+ f = EGLPNUM_TYPENAME_EGlpNumAllocArray (ncols);
+
+ for (j = 0; j < ncols; j++)
+ {
+ if (cols[j].del || cols[j].coltype != ILL_PRE_COL_STRUC)
+ {
+ s[j] = EGLPNUM_TYPENAME_ILL_MAXINT; /* EGLPNUM_TYPENAME_ILL_MAXINT means no longer eligible */
+ }
+ else
+ {
+ s[j] = 0; /* 0 means eligible, >0 means in a group */
+ nu++; /* Tracks the number of eligible rows */
+ }
+ }
+
+ for (i = 0; i < nrows; i++)
+ {
+ r = &rows[i];
+ if (r->del)
+ continue;
+
+ n = 0;
+ t0 = t++;
+
+ for (k = 0; k < r->deg; k++)
+ {
+ if (r->adj[k]->del)
+ continue;
+
+ ci = r->adj[k]->col;
+ if (s[ci] == 0)
+ {
+ s[ci] = t0;
+ EGLPNUM_TYPENAME_EGlpNumCopy (f[ci], r->adj[k]->coef);
+ c0 = ci;
+ n++;
+ }
+ else if (s[ci] < t0)
+ {
+ got = 0;
+ for (k2 = k + 1; k2 < r->deg; k2++)
+ {
+ if (r->adj[k2]->del)
+ continue;
+
+ j = r->adj[k2]->col;
+ if (s[j] == s[ci])
+ {
+ /*q = (r->adj[k]->coef * (f[j])) / (f[ci] * (r->adj[k2]->coef)); */
+ EGLPNUM_TYPENAME_EGlpNumCopy (q, r->adj[k]->coef);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (q, f[j]);
+ EGLPNUM_TYPENAME_EGlpNumDivTo (q, f[ci]);
+ EGLPNUM_TYPENAME_EGlpNumDivTo (q, r->adj[k2]->coef);
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqual (q, EGLPNUM_TYPENAME_oneLpNum, ILL_PRE_ZERO_TOL))
+ {
+ s[ci] = t;
+ s[j] = t;
+ got++;
+ }
+ }
+ }
+ if (got)
+ {
+ t++;
+ }
+ else
+ {
+ s[ci] = EGLPNUM_TYPENAME_ILL_MAXINT;
+ if (--nu == 0)
+ goto DONE;
+ }
+ }
+ }
+
+ if (n == 1)
+ {
+ s[c0] = EGLPNUM_TYPENAME_ILL_MAXINT;
+ if (--nu == 0)
+ goto DONE;
+ }
+ }
+
+DONE:
+
+ {
+ int dcount;
+ int *dcnt;
+ int *dlist;
+
+ rval = gather_dup_lists (s, ncols, &dcount, &dcnt, &dlist);
+ ILL_CLEANUP_IF (rval);
+ }
+
+ QSlog("Time in duplicate_cols: %.2f (seconds)", ILLutil_zeit () - szeit);
+
+CLEANUP:
+
+ ILL_IFFREE (s, int);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (f);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (q);
+ ILL_RETURN (rval, "duplicate_cols");
+}
+
+static int gather_dup_lists (
+ /* graph *G, */ int *s,
+ /* double *f, */
+ int count,
+ int *duptotal,
+ int **dupcnt,
+ int **dupind)
+{
+ int rval = 0;
+ int *cnt = 0;
+ int *ind = 0;
+ int *beg = 0;
+ int i, smax = 0, ndup = 0, total = 0;
+
+ *duptotal = 0;
+ *dupcnt = 0;
+ *dupind = 0;
+
+
+ for (i = 0; i < count; i++)
+ {
+ if (s[i] < EGLPNUM_TYPENAME_ILL_MAXINT && s[i] > smax)
+ smax = s[i];
+ }
+ if (smax == 0)
+ goto CLEANUP;
+
+ ILL_SAFE_MALLOC (cnt, smax + 1, int);
+
+ ILL_SAFE_MALLOC (ind, smax + 1, int);
+
+ for (i = 0; i < smax + 1; i++)
+ {
+ cnt[i] = 0;
+ }
+
+ for (i = 0; i < count; i++)
+ {
+ if (s[i] < EGLPNUM_TYPENAME_ILL_MAXINT)
+ {
+ cnt[s[i]]++;
+ }
+ }
+
+ if (cnt[0] > 0)
+ QSlog("%d Empty Lines", cnt[0]);
+
+ QSlog("Duplicate Classes:");
+ for (i = 1; i < smax + 1; i++)
+ {
+ if (cnt[i] > 1)
+ {
+ ndup++;
+ QSlog(" %d", cnt[i]);
+ }
+ }
+ QSlog(" Number %d\n", ndup);
+
+ if (ndup == 0)
+ goto CLEANUP;
+
+ ILL_SAFE_MALLOC (beg, ndup, int);
+
+ for (i = 1, ndup = 0; i < smax + 1; i++)
+ {
+ if (cnt[i] > 1)
+ {
+ beg[ndup] = total;
+ total += cnt[i];
+ ind[i] = ndup;
+ ndup++;
+ }
+ }
+
+ if (total == 0)
+ goto CLEANUP;
+
+ ILL_SAFE_MALLOC (*dupcnt, ndup, int);
+
+ ILL_SAFE_MALLOC (*dupind, total, int);
+
+ for (i = 0; i < ndup; i++)
+ {
+ (*dupcnt)[i] = 0;
+ }
+
+ for (i = 0; i < count; i++)
+ {
+ if (s[i] < EGLPNUM_TYPENAME_ILL_MAXINT && s[i] > 0)
+ {
+ if (cnt[s[i]] > 1)
+ {
+ (*dupind)[beg[ind[s[i]]] + (*dupcnt)[ind[s[i]]]] = i;
+ (*dupcnt)[ind[s[i]]]++;
+ }
+ }
+ }
+
+ for (i = 0; i < ndup; i++)
+ {
+ int j;
+
+ for (j = beg[i]; j < beg[i] + (*dupcnt)[i]; j++)
+ {
+ QSlog(" %d", (*dupind)[j]);
+ }
+ QSlog(" | ");
+ }
+
+ *duptotal = ndup;
+
+CLEANUP:
+
+ ILL_IFFREE (cnt, int);
+ ILL_IFFREE (ind, int);
+ ILL_IFFREE (beg, int);
+
+ ILL_RETURN (rval, "gather_dup_lists");
+}
+
+static void set_fixed_variable (
+ graph * G,
+ int j,
+ EGLPNUM_TYPE val)
+{
+ int k;
+ edge *e;
+
+ G->cols[j].del = 1;
+ for (k = 0; k < G->cols[j].deg; k++)
+ {
+ e = G->cols[j].adj[k];
+ if (e->del == 0)
+ {
+ /*G->rows[e->row].rhs -= (e->coef * val); */
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (G->rows[e->row].rhs, e->coef, val);
+ e->del = 1;
+ }
+ }
+}
+
+static void get_implied_rhs_bounds (
+ graph * G,
+ int i,
+ EGLPNUM_TYPE * lb,
+ EGLPNUM_TYPE * ub)
+{
+ int k;
+ EGLPNUM_TYPE l, u;
+ node *cols = G->cols;
+ node *rows = G->rows;
+ edge *e;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (u);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (l);
+
+ EGLPNUM_TYPENAME_EGlpNumZero (l);
+ for (k = 0; k < rows[i].deg; k++)
+ {
+ e = rows[i].adj[k];
+ if (e->del == 0)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (e->coef))
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (cols[e->col].upper, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (l, EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+ break;
+ }
+ else
+ {
+ /*l += (e->coef * cols[e->col].upper); */
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (l, e->coef, cols[e->col].upper);
+ }
+ }
+ else if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (e->coef))
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (cols[e->col].lower, EGLPNUM_TYPENAME_ILL_MINDOUBLE))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (l, EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+ break;
+ }
+ else
+ {
+ /*l += (e->coef * cols[e->col].lower); */
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (l, e->coef, cols[e->col].lower);
+ }
+ }
+ }
+ }
+
+ EGLPNUM_TYPENAME_EGlpNumZero (u);
+ for (k = 0; k < rows[i].deg; k++)
+ {
+ e = rows[i].adj[k];
+ if (e->del == 0)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (e->coef ))
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (cols[e->col].lower, EGLPNUM_TYPENAME_ILL_MINDOUBLE))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (u, EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+ }
+ else
+ {
+ /*u += (e->coef * cols[e->col].lower); */
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (u, e->coef, cols[e->col].lower);
+ }
+ }
+ else if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (e->coef))
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (cols[e->col].upper, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (u, EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+ }
+ else
+ {
+ /*u += (e->coef * cols[e->col].upper); */
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (u, e->coef, cols[e->col].upper);
+ }
+ }
+ }
+ }
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (*lb, l);
+ EGLPNUM_TYPENAME_EGlpNumCopy (*ub, u);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (u);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (l);
+}
+
+static void get_implied_variable_bounds (
+ graph * G,
+ int j,
+ edge * a_ij,
+ EGLPNUM_TYPE * lb,
+ EGLPNUM_TYPE * ub)
+{
+ int i = a_ij->row;
+ EGLPNUM_TYPE l, u;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (u);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (l);
+
+ get_implied_rhs_bounds (G, i, &l, &u);
+ EGLPNUM_TYPENAME_EGlpNumCopy (*lb, EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+ EGLPNUM_TYPENAME_EGlpNumCopy (*ub, EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (ILL_PRE_FEAS_TOL, a_ij->coef))
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (u, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+ {
+ /**lb = (G->rows[i].rhs - u) / a_ij->coef + G->cols[j].upper;*/
+ EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (*lb, G->rows[i].rhs, u, a_ij->coef);
+ EGLPNUM_TYPENAME_EGlpNumAddTo (*lb, G->cols[j].upper);
+ }
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_ILL_MINDOUBLE, l))
+ {
+ /**ub = (G->rows[i].rhs - l) / a_ij->coef + G->cols[j].lower;*/
+ EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (*ub, G->rows[i].rhs, l, a_ij->coef);
+ EGLPNUM_TYPENAME_EGlpNumAddTo (*ub, G->cols[j].lower);
+ }
+ }
+ else if (EGLPNUM_TYPENAME_EGlpNumIsLess (a_ij->coef, ILL_PRE_FEAS_TOL))
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_ILL_MINDOUBLE, l))
+ {
+ /**lb = (G->rows[i].rhs - l) / a_ij->coef + G->cols[j].upper;*/
+ EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (*lb, G->rows[i].rhs, l, a_ij->coef);
+ EGLPNUM_TYPENAME_EGlpNumAddTo (*lb, G->cols[j].upper);
+ }
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (u, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+ {
+ /**ub = (G->rows[i].rhs - u) / a_ij->coef + G->cols[j].lower;*/
+ EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (*ub, G->rows[i].rhs, u, a_ij->coef);
+ EGLPNUM_TYPENAME_EGlpNumAddTo (*ub, G->cols[j].lower);
+ }
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (u);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (l);
+}
+
+static int get_next_preop (
+ EGLPNUM_TYPENAME_ILLlp_predata * pre,
+ EGLPNUM_TYPENAME_ILLlp_preop ** op)
+{
+ int rval = 0;
+
+ if (pre->opcount >= pre->opsize)
+ {
+ pre->opsize *= 1.3;
+ pre->opsize += 1000;
+ if (pre->opsize < pre->opcount + 1)
+ pre->opsize = pre->opcount + 1;
+ pre->oplist = EGrealloc (pre->oplist, sizeof (EGLPNUM_TYPENAME_ILLlp_preop) * pre->opsize);
+ //rval = ILLutil_reallocrus_scale ((void **) &pre->oplist,
+ // &pre->opsize, pre->opcount + 1, 1.3,
+ // sizeof (EGLPNUM_TYPENAME_ILLlp_preop));
+ //ILL_CLEANUP_IF (rval);
+ }
+ *op = &pre->oplist[pre->opcount];
+ EGLPNUM_TYPENAME_ILLlp_preop_init (*op);
+
+//CLEANUP:
+
+ ILL_RETURN (rval, "get_next_preop");
+}
+
+static int add_to_list (
+ ILLptrworld * world,
+ intptr ** list,
+ int i)
+{
+ int rval = 0;
+ intptr *ip;
+
+ ip = intptralloc (world);
+ if (!ip)
+ {
+ rval = 1;
+ goto CLEANUP;
+ }
+ ip->this_val = i;
+ ip->next = *list;
+ *list = ip;
+
+CLEANUP:
+
+ ILL_RETURN (rval, "add_to_list");
+}
+
+static int build_graph (
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ graph * G)
+{
+ int rval = 0;
+ int ncols = lp->ncols;
+ int nrows = lp->nrows;
+ int nzcount = lp->nzcount;
+ int i, j, k, stop, count;
+ edge *edgelist;
+ node *rows, *cols;
+ EGLPNUM_TYPENAME_ILLmatrix *A = &lp->A;
+
+ G->objsense = lp->objsense;
+
+ ILL_SAFE_MALLOC (G->rows, nrows, node);
+ if (!G->rows)
+ {
+ QSlog("out of memory in build_graph");
+ rval = 1;
+ goto CLEANUP;
+ }
+ rows = G->rows;
+
+ for (i = 0; i < nrows; i++)
+ {
+ rows[i].rowsense = lp->sense[i];
+ rows[i].deg = 0;
+ }
+
+ ILL_SAFE_MALLOC (G->cols, ncols, node);
+ ILL_SAFE_MALLOC (G->edgelist, nzcount, edge);
+ for (i = nzcount; i--;)
+ EGLPNUM_TYPENAME_EGlpNumInitVar ((G->edgelist[i].coef));
+ G->nzcount = nzcount;
+ ILL_SAFE_MALLOC (G->adjspace, 2 * nzcount, edge *);
+
+ if (!G->cols || !G->edgelist || !G->adjspace)
+ {
+ QSlog("out of memory in build_graph");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ cols = G->cols;
+ edgelist = G->edgelist;
+
+ for (j = 0; j < ncols; j++)
+ {
+ stop = A->matbeg[j] + A->matcnt[j];
+ for (k = A->matbeg[j]; k < stop; k++)
+ {
+ rows[A->matind[k]].deg++;
+ }
+ }
+
+ for (i = 0, count = 0; i < nrows; i++)
+ {
+ rows[i].adj = G->adjspace + count;
+ count += rows[i].deg;
+ rows[i].deg = 0;
+ }
+
+ for (j = 0; j < ncols; j++)
+ {
+ cols[j].adj = G->adjspace + count;
+ count += A->matcnt[j];
+ cols[j].deg = 0;
+ cols[j].coltype = ILL_PRE_COL_STRUC;
+ }
+ for (i = 0; i < nrows; i++)
+ {
+ cols[lp->rowmap[i]].coltype = ILL_PRE_COL_LOGICAL;
+ }
+
+ for (j = 0, count = 0; j < ncols; j++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (cols[j].obj, lp->obj[j]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (cols[j].lower, lp->lower[j]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (cols[j].upper, lp->upper[j]);
+ stop = A->matbeg[j] + A->matcnt[j];
+ for (k = A->matbeg[j]; k < stop; k++)
+ {
+ i = A->matind[k];
+ rows[i].adj[rows[i].deg++] = &(edgelist[count]);
+ cols[j].adj[cols[j].deg++] = &(edgelist[count]);
+ edgelist[count].row = i;
+ edgelist[count].col = j;
+ EGLPNUM_TYPENAME_EGlpNumCopy (edgelist[count].coef, A->matval[k]);
+ edgelist[count].mark = 0;
+ edgelist[count].del = 0;
+ edgelist[count].coltype = cols[j].coltype;
+ count++;
+ }
+ }
+ if (count != nzcount)
+ {
+ QSlog("counts are off in build_graph");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ G->ecount = count;
+ G->nrows = nrows;
+ G->ncols = ncols;
+
+ for (i = 0; i < G->nrows; i++)
+ {
+ G->rows[i].del = 0;
+ EGLPNUM_TYPENAME_EGlpNumCopy (G->rows[i].rhs, lp->rhs[i]);
+ }
+ for (j = 0; j < G->ncols; j++)
+ {
+ G->cols[j].del = 0;
+ }
+
+CLEANUP:
+
+ ILL_RETURN (rval, "build_graph");
+}
+
+static void dump_graph (
+ graph * G)
+{
+ int i, j, k;
+
+ QSlog("ecount = %d, nrows = %d, ncols = %d",
+ G->ecount, G->nrows, G->ncols);
+
+ for (i = 0; i < G->nrows; i++)
+ {
+ QSlog("Row %d:", i);
+ for (k = 0; k < G->rows[i].deg; k++)
+ {
+ QSlog(" %d", G->rows[i].adj[k]->col);
+ if (G->rows[i].adj[k]->coltype == ILL_PRE_COL_LOGICAL)
+ QSlog("S");
+ QSlog("(%g)", EGLPNUM_TYPENAME_EGlpNumToLf (G->rows[i].adj[k]->coef));
+ }
+ QSlog(" rhs: %g", EGLPNUM_TYPENAME_EGlpNumToLf (G->rows[i].rhs));
+ if (G->rows[i].del) QSlog(" (deleted)");
+ }
+
+ for (j = 0; j < G->ncols; j++)
+ {
+ if (G->cols[j].coltype == ILL_PRE_COL_LOGICAL)
+ {
+ QSlog("Slk %d:", j);
+ }
+ else
+ {
+ QSlog("Col %d:", j);
+ }
+ for (k = 0; k < G->cols[j].deg; k++)
+ {
+ QSlog(" %d", G->cols[j].adj[k]->row);
+ }
+ QSlog(" obj: %g bnd: (%g, %g)", EGLPNUM_TYPENAME_EGlpNumToLf (G->cols[j].obj),
+ EGLPNUM_TYPENAME_EGlpNumToLf (G->cols[j].lower), EGLPNUM_TYPENAME_EGlpNumToLf (G->cols[j].upper));
+ if (G->cols[j].del) QSlog(" (deleted)");
+ }
+}
+
+static void init_graph (
+ graph * G)
+{
+ if (G)
+ {
+ G->edgelist = 0;
+ G->rows = 0;
+ G->cols = 0;
+ G->ecount = 0;
+ G->nrows = 0;
+ G->ncols = 0;
+ G->adjspace = 0;
+ ILLptrworld_init (&G->intptrworld);
+ }
+}
+
+static void free_graph (
+ graph * G)
+{
+ register int i;
+
+ if (G)
+ {
+ int total, onlist;
+
+ for (i = G->nzcount; i--;)
+ EGLPNUM_TYPENAME_EGlpNumClearVar ((G->edgelist[i].coef));
+ ILL_IFFREE (G->edgelist, edge);
+ ILL_IFFREE (G->rows, node);
+ ILL_IFFREE (G->cols, node);
+ ILL_IFFREE (G->adjspace, edge *);
+ if (intptr_check_leaks (&G->intptrworld, &total, &onlist))
+ {
+ QSlog("WARNING: %d outstanding intptrs", total - onlist);
+ }
+ ILLptrworld_delete (&G->intptrworld);
+ init_graph (G);
+ }
+}
+
+int EGLPNUM_TYPENAME_ILLlp_sinfo_print (
+ EGLPNUM_TYPENAME_ILLlp_sinfo * s)
+{
+ int rval = 0;
+ int i;
+ EGLPNUM_TYPENAME_ILLlpdata lp;
+ char *sense = 0;
+
+ EGLPNUM_TYPENAME_ILLlpdata_init (&lp);
+
+ lp.nrows = s->nrows;
+ lp.ncols = s->ncols;
+ lp.nzcount = s->nzcount;
+ lp.objsense = s->objsense;
+ lp.obj = s->obj;
+ lp.rhs = s->rhs;
+ lp.lower = s->lower;
+ lp.upper = s->upper;
+ lp.A.matval = s->A.matval;
+ lp.A.matcnt = s->A.matcnt;
+ lp.A.matbeg = s->A.matbeg;
+ lp.A.matind = s->A.matind;
+ lp.rownames = 0;
+ lp.colnames = s->colnames;
+ lp.objname = 0;
+ lp.probname = 0;
+ lp.intmarker = 0;
+
+ ILL_SAFE_MALLOC (sense, s->nrows, char);
+
+ if (!sense)
+ {
+ QSlog("out of memory in EGLPNUM_TYPENAME_ILLlp_sinfo_print");
+ rval = 1;
+ goto CLEANUP;
+ }
+ for (i = 0; i < s->nrows; i++)
+ {
+ sense[i] = 'E';
+ }
+ lp.sense = sense;
+
+/*
+ rval = ILLlpdata_writelp (&lp, 0);
+ ILL_CLEANUP_IF (rval);
+*/
+
+CLEANUP:
+
+ ILL_IFFREE (sense, char);
+
+ ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLlp_sinfo_print");
+}
+
+void EGLPNUM_TYPENAME_ILLlp_sinfo_init (
+ EGLPNUM_TYPENAME_ILLlp_sinfo * sinfo)
+{
+ if (sinfo)
+ {
+ sinfo->ncols = 0;
+ sinfo->nrows = 0;
+ sinfo->nzcount = 0;
+ sinfo->rowsize = 0;
+ sinfo->colsize = 0;
+ sinfo->obj = 0;
+ sinfo->rhs = 0;
+ sinfo->lower = 0;
+ sinfo->upper = 0;
+ sinfo->colnames = 0;
+ sinfo->objsense = EGLPNUM_TYPENAME_ILL_MIN;
+ EGLPNUM_TYPENAME_ILLmatrix_init (&sinfo->A);
+ }
+}
+
+void EGLPNUM_TYPENAME_ILLlp_sinfo_free (
+ EGLPNUM_TYPENAME_ILLlp_sinfo * sinfo)
+{
+ if (sinfo)
+ {
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (sinfo->obj);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (sinfo->lower);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (sinfo->upper);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (sinfo->rhs);
+ EGLPNUM_TYPENAME_ILLmatrix_free (&sinfo->A);
+ if (sinfo->colnames)
+ {
+ int i;
+
+ for (i = 0; i < sinfo->ncols; i++)
+ {
+ ILL_IFFREE (sinfo->colnames[i], char);
+ }
+ ILL_IFFREE (sinfo->colnames, char *);
+ }
+ EGLPNUM_TYPENAME_ILLlp_sinfo_init (sinfo);
+ }
+}
+
+void EGLPNUM_TYPENAME_ILLlp_predata_init (
+ EGLPNUM_TYPENAME_ILLlp_predata * pre)
+{
+ if (pre)
+ {
+ pre->opcount = 0;
+ pre->opsize = 0;
+ pre->oplist = 0;
+ pre->r_nrows = 0;
+ pre->r_ncols = 0;
+ pre->colmap = 0;
+ pre->rowmap = 0;
+ pre->colscale = 0;
+ pre->rowscale = 0;
+ pre->colfixval = 0;
+ pre->rowfixval = 0;
+ }
+}
+
+void EGLPNUM_TYPENAME_ILLlp_predata_free (
+ EGLPNUM_TYPENAME_ILLlp_predata * pre)
+{
+ if (pre)
+ {
+ int i;
+
+ for (i = 0; i < pre->opcount; i++)
+ {
+ EGLPNUM_TYPENAME_ILLlp_preop_free (&pre->oplist[i]);
+ }
+ ILL_IFFREE (pre->oplist, EGLPNUM_TYPENAME_ILLlp_preop);
+ ILL_IFFREE (pre->colmap, int);
+ ILL_IFFREE (pre->rowmap, int);
+
+ ILL_IFFREE (pre->colscale, EGLPNUM_TYPE);
+ ILL_IFFREE (pre->rowscale, EGLPNUM_TYPE);
+ ILL_IFFREE (pre->colfixval, EGLPNUM_TYPE);
+ ILL_IFFREE (pre->rowfixval, EGLPNUM_TYPE);
+ EGLPNUM_TYPENAME_ILLlp_predata_init (pre);
+ }
+}
+
+void EGLPNUM_TYPENAME_ILLlp_preop_init (
+ EGLPNUM_TYPENAME_ILLlp_preop * op)
+{
+ if (op)
+ {
+ op->ptype = 0;
+ op->rowindex = -1;
+ op->colindex = -1;
+ EGLPNUM_TYPENAME_ILLlp_preline_init (&op->line);
+ }
+}
+
+void EGLPNUM_TYPENAME_ILLlp_preop_free (
+ EGLPNUM_TYPENAME_ILLlp_preop * op)
+{
+ if (op)
+ {
+ EGLPNUM_TYPENAME_ILLlp_preline_free (&op->line);
+ EGLPNUM_TYPENAME_ILLlp_preop_init (op);
+ }
+}
+
+void EGLPNUM_TYPENAME_ILLlp_preline_init (
+ EGLPNUM_TYPENAME_ILLlp_preline * line)
+{
+ if (line)
+ {
+ EGLPNUM_TYPENAME_EGlpNumInitVar (line->rhs);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (line->obj);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (line->upper);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (line->lower);
+ EGLPNUM_TYPENAME_EGlpNumZero (line->rhs);
+ EGLPNUM_TYPENAME_EGlpNumZero (line->obj);
+ EGLPNUM_TYPENAME_EGlpNumZero (line->upper);
+ EGLPNUM_TYPENAME_EGlpNumZero (line->lower);
+ line->count = 0;
+ line->ind = 0;
+ line->val = 0;
+ }
+}
+
+void EGLPNUM_TYPENAME_ILLlp_preline_free (
+ EGLPNUM_TYPENAME_ILLlp_preline * line)
+{
+ if (line)
+ {
+ EGLPNUM_TYPENAME_EGlpNumClearVar (line->rhs);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (line->obj);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (line->upper);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (line->lower);
+ ILL_IFFREE (line->ind, int);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (line->val);
+ //EGLPNUM_TYPENAME_ILLlp_preline_init (line);
+ }
+}
diff --git a/qsopt_ex/presolve.h b/qsopt_ex/presolve.h
new file mode 100644
index 0000000..172fc8a
--- /dev/null
+++ b/qsopt_ex/presolve.h
@@ -0,0 +1,41 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+#ifndef EGLPNUM_TYPENAME_PRESOLVE_H
+#define EGLPNUM_TYPENAME_PRESOLVE_H
+
+#include "lpdata_EGLPNUM_TYPENAME.h"
+
+void EGLPNUM_TYPENAME_ILLlp_sinfo_init(EGLPNUM_TYPENAME_ILLlp_sinfo * sinfo);
+void EGLPNUM_TYPENAME_ILLlp_sinfo_free(EGLPNUM_TYPENAME_ILLlp_sinfo * sinfo);
+int EGLPNUM_TYPENAME_ILLlp_sinfo_print(EGLPNUM_TYPENAME_ILLlp_sinfo * s);
+
+void EGLPNUM_TYPENAME_ILLlp_predata_init(EGLPNUM_TYPENAME_ILLlp_predata * pre);
+void EGLPNUM_TYPENAME_ILLlp_predata_free(EGLPNUM_TYPENAME_ILLlp_predata * pre);
+
+void EGLPNUM_TYPENAME_ILLlp_preop_init(EGLPNUM_TYPENAME_ILLlp_preop * op);
+void EGLPNUM_TYPENAME_ILLlp_preop_free(EGLPNUM_TYPENAME_ILLlp_preop * op);
+
+void EGLPNUM_TYPENAME_ILLlp_preline_init(EGLPNUM_TYPENAME_ILLlp_preline * line);
+void EGLPNUM_TYPENAME_ILLlp_preline_free(EGLPNUM_TYPENAME_ILLlp_preline * line);
+
+#endif /* ! EGLPNUM_TYPENAME_PRESOLVE_H */
diff --git a/qsopt_ex/price.c b/qsopt_ex/price.c
new file mode 100644
index 0000000..dcc6e9c
--- /dev/null
+++ b/qsopt_ex/price.c
@@ -0,0 +1,1640 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: price.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+//static int TRACE = 0;
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "allocrus.h"
+#include "eg_lpnum.h"
+#include "eg_numutil_EGLPNUM_TYPENAME.h"
+#include "eg_io.h"
+#include "except.h"
+#include "util.h"
+
+#include "stddefs.h"
+#include "qsopt_EGLPNUM_TYPENAME.h"
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+#include "fct_EGLPNUM_TYPENAME.h"
+#include "price_EGLPNUM_TYPENAME.h"
+#include "basis_EGLPNUM_TYPENAME.h"
+#include "dstruct_EGLPNUM_TYPENAME.h"
+
+#define MULTIP 1
+#define PRICE_DEBUG 0
+
+
+static void update_d_scaleinf (
+ EGLPNUM_TYPENAME_price_info * const p,
+ EGLPNUM_TYPENAME_heap * const h,
+ int const j,
+ EGLPNUM_TYPE inf,
+ int const prule),
+ update_p_scaleinf (
+ EGLPNUM_TYPENAME_price_info * const p,
+ EGLPNUM_TYPENAME_heap * const h,
+ int const i,
+ EGLPNUM_TYPE inf,
+ int const prule);
+
+static void compute_dualI_inf (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ int const j,
+ EGLPNUM_TYPE * const inf),
+ compute_dualII_inf (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ int const j,
+ EGLPNUM_TYPE * const inf),
+ compute_primalI_inf (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ int const i,
+ EGLPNUM_TYPE * const inf),
+ compute_primalII_inf (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ int const i,
+ EGLPNUM_TYPE * const inf);
+
+void EGLPNUM_TYPENAME_ILLprice_free_heap (
+ EGLPNUM_TYPENAME_price_info * const pinf)
+{
+ EGLPNUM_TYPENAME_ILLheap_free (&(pinf->h));
+}
+
+int EGLPNUM_TYPENAME_ILLprice_build_heap (
+ EGLPNUM_TYPENAME_price_info * const pinf,
+ int const nkeys,
+ EGLPNUM_TYPE * keylist)
+{
+ EGLPNUM_TYPENAME_ILLheap_init (&(pinf->h));
+ EGLPNUM_TYPENAME_EGlpNumSet (pinf->htrigger,
+ 1.0 +
+ (double) nkeys / (PARAM_HEAP_RATIO * ILLutil_our_log2 (nkeys)));
+ return EGLPNUM_TYPENAME_ILLheap_build (&(pinf->h), nkeys, keylist);
+}
+
+int EGLPNUM_TYPENAME_ILLprice_test_for_heap (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_price_info * const pinf,
+ int const nkeys,
+ EGLPNUM_TYPE * keylist,
+ int const algo,
+ int const upd)
+{
+ EGLPNUM_TYPENAME_heap *const h = &(pinf->h);
+ int rval = 0;
+ EGLPNUM_TYPE ravg;
+
+ if (upd != 0)
+ {
+ EGLPNUM_TYPENAME_EGlpNumInitVar (ravg);
+ if (algo == PRIMAL_SIMPLEX)
+ EGLPNUM_TYPENAME_EGlpNumCopy (ravg, lp->cnts->za_ravg);
+ else
+ EGLPNUM_TYPENAME_EGlpNumCopy (ravg, lp->cnts->y_ravg);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLeq (ravg, pinf->htrigger))
+ pinf->hineff--;
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumDivUiTo (ravg, 2U);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (pinf->htrigger, ravg))
+ pinf->hineff++;
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ravg);
+ }
+ if (h->hexist == 0 && pinf->hineff <= 0)
+ {
+ rval = EGLPNUM_TYPENAME_ILLprice_build_heap (pinf, nkeys, keylist);
+ CHECKRVALG (rval, CLEANUP);
+ }
+ else if (h->hexist != 0 && pinf->hineff >= PARAM_HEAP_UTRIGGER)
+ {
+ EGLPNUM_TYPENAME_ILLprice_free_heap (pinf);
+ /*
+ * QSlog("freeing EGLPNUM_TYPENAME_heap ..");
+ * QSlog("iter = %d, ravg = %.2f, trigger = %.2f",
+ * lp->cnts->tot_iter, ravg, pinf->htrigger);
+ */
+ }
+
+CLEANUP:
+ if (rval)
+ EGLPNUM_TYPENAME_ILLprice_free_heap (pinf);
+ return rval;
+}
+
+void EGLPNUM_TYPENAME_ILLprice_init_pricing_info (
+ EGLPNUM_TYPENAME_price_info * const pinf)
+{
+ pinf->p_strategy = -1;
+ pinf->d_strategy = -1;
+ pinf->pI_price = -1;
+ pinf->pII_price = -1;
+ pinf->dI_price = -1;
+ pinf->dII_price = -1;
+ pinf->cur_price = -1;
+ pinf->p_scaleinf = 0;
+ pinf->d_scaleinf = 0;
+ pinf->pdinfo.norms = 0;
+ pinf->pdinfo.refframe = 0;
+ pinf->psinfo.norms = 0;
+ pinf->ddinfo.norms = 0;
+ pinf->ddinfo.refframe = 0;
+ pinf->dsinfo.norms = 0;
+ pinf->dmpinfo.gstart = pinf->pmpinfo.gstart = 0;
+ pinf->dmpinfo.gshift = pinf->pmpinfo.gshift = 0;
+ pinf->dmpinfo.gsize = pinf->pmpinfo.gsize = 0;
+ pinf->dmpinfo.bucket = pinf->pmpinfo.bucket = 0;
+ pinf->dmpinfo.perm = pinf->pmpinfo.perm = 0;
+ pinf->dmpinfo.infeas = pinf->pmpinfo.infeas = 0;
+ EGLPNUM_TYPENAME_ILLheap_init (&(pinf->h));
+ EGLPNUM_TYPENAME_EGlpNumZero (pinf->htrigger);
+ pinf->hineff = 0;
+}
+
+void EGLPNUM_TYPENAME_ILLprice_free_pricing_info (
+ EGLPNUM_TYPENAME_price_info * const pinf)
+{
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (pinf->p_scaleinf);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (pinf->d_scaleinf);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (pinf->pdinfo.norms);
+ ILL_IFFREE (pinf->pdinfo.refframe, int);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (pinf->psinfo.norms);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (pinf->ddinfo.norms);
+ ILL_IFFREE (pinf->ddinfo.refframe, int);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (pinf->dsinfo.norms);
+
+ EGLPNUM_TYPENAME_ILLprice_free_mpartial_info (&(pinf->pmpinfo));
+ EGLPNUM_TYPENAME_ILLprice_free_mpartial_info (&(pinf->dmpinfo));
+ EGLPNUM_TYPENAME_ILLprice_free_heap (pinf);
+}
+
+int EGLPNUM_TYPENAME_ILLprice_build_pricing_info (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_price_info * const pinf,
+ int const phase)
+{
+ int rval = 0;
+ int p_price = -1;
+ int d_price = -1;
+
+ switch (phase)
+ {
+ case PRIMAL_PHASEI:
+ p_price = pinf->pI_price;
+ break;
+ case PRIMAL_PHASEII:
+ p_price = pinf->pII_price;
+ break;
+ case DUAL_PHASEI:
+ d_price = pinf->dI_price;
+ break;
+ case DUAL_PHASEII:
+ d_price = pinf->dII_price;
+ break;
+ }
+
+ if (p_price != -1)
+ {
+ pinf->cur_price = p_price;
+
+ if (p_price == QS_PRICE_PDANTZIG || p_price == QS_PRICE_PDEVEX ||
+ p_price == QS_PRICE_PSTEEP)
+ {
+ pinf->p_strategy = COMPLETE_PRICING;
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (pinf->d_scaleinf);
+ pinf->d_scaleinf = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nnbasic);
+ }
+ else if (p_price == QS_PRICE_PMULTPARTIAL)
+ pinf->p_strategy = MULTI_PART_PRICING;
+
+ switch (p_price)
+ {
+ case QS_PRICE_PDEVEX:
+ if (pinf->pdinfo.norms)
+ return rval;
+ rval = EGLPNUM_TYPENAME_ILLprice_build_pdevex_norms (lp, &(pinf->pdinfo), 0);
+ CHECKRVALG(rval,CLEANUP);
+ break;
+ case QS_PRICE_PSTEEP:
+ if (pinf->psinfo.norms)
+ return rval;
+ rval = EGLPNUM_TYPENAME_ILLprice_build_psteep_norms (lp, &(pinf->psinfo));
+ CHECKRVALG(rval,CLEANUP);
+ break;
+ case QS_PRICE_PMULTPARTIAL:
+ rval = EGLPNUM_TYPENAME_ILLprice_build_mpartial_info (lp, pinf, COL_PRICING);
+ CHECKRVALG(rval,CLEANUP);
+ break;
+ }
+ }
+ else if (d_price != -1)
+ {
+ pinf->cur_price = d_price;
+
+ if (d_price == QS_PRICE_DDANTZIG || d_price == QS_PRICE_DSTEEP ||
+ d_price == QS_PRICE_DDEVEX)
+ {
+ pinf->d_strategy = COMPLETE_PRICING;
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (pinf->p_scaleinf);
+ pinf->p_scaleinf = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+ }
+ else if (d_price == QS_PRICE_DMULTPARTIAL)
+ pinf->d_strategy = MULTI_PART_PRICING;
+
+ switch (d_price)
+ {
+ case QS_PRICE_DSTEEP:
+ if (pinf->dsinfo.norms)
+ return rval;
+ rval = EGLPNUM_TYPENAME_ILLprice_build_dsteep_norms (lp, &(pinf->dsinfo));
+ CHECKRVALG(rval,CLEANUP);
+ break;
+ case QS_PRICE_DMULTPARTIAL:
+ rval = EGLPNUM_TYPENAME_ILLprice_build_mpartial_info (lp, pinf, ROW_PRICING);
+ CHECKRVALG(rval,CLEANUP);
+ break;
+ case QS_PRICE_DDEVEX:
+ if (pinf->ddinfo.norms)
+ return rval;
+ rval = EGLPNUM_TYPENAME_ILLprice_build_ddevex_norms (lp, &(pinf->ddinfo), 0);
+ CHECKRVALG(rval,CLEANUP);
+ break;
+ }
+ }
+
+CLEANUP:
+ if (rval)
+ EGLPNUM_TYPENAME_ILLprice_free_pricing_info (pinf);
+ EG_RETURN(rval);
+}
+
+int EGLPNUM_TYPENAME_ILLprice_update_pricing_info (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_price_info * const pinf,
+ int const phase,
+ EGLPNUM_TYPENAME_svector * const wz,
+ int const eindex,
+ int const lindex,
+ EGLPNUM_TYPE y)
+{
+ int rval = 0;
+ int p_price = -1;
+ int d_price = -1;
+
+ switch (phase)
+ {
+ case PRIMAL_PHASEI:
+ p_price = pinf->pI_price;
+ break;
+ case PRIMAL_PHASEII:
+ p_price = pinf->pII_price;
+ break;
+ case DUAL_PHASEI:
+ d_price = pinf->dI_price;
+ break;
+ case DUAL_PHASEII:
+ d_price = pinf->dII_price;
+ break;
+ }
+
+ if (p_price != -1)
+ {
+ if (p_price == QS_PRICE_PDEVEX)
+ {
+ rval = EGLPNUM_TYPENAME_ILLprice_update_pdevex_norms (lp, &(pinf->pdinfo), eindex, y);
+ CHECKRVALG(rval,CLEANUP);
+ }
+ else if (p_price == QS_PRICE_PSTEEP)
+ EGLPNUM_TYPENAME_ILLprice_update_psteep_norms (lp, &(pinf->psinfo), wz, eindex, y);
+ }
+ else if (d_price != -1)
+ {
+ if (d_price == QS_PRICE_DSTEEP)
+ EGLPNUM_TYPENAME_ILLprice_update_dsteep_norms (lp, &(pinf->dsinfo), wz, lindex, y);
+ else if (d_price == QS_PRICE_DDEVEX)
+ {
+ rval = EGLPNUM_TYPENAME_ILLprice_update_ddevex_norms (lp, &(pinf->ddinfo), lindex, y);
+ CHECKRVALG(rval,CLEANUP);
+ }
+ }
+CLEANUP:
+ EG_RETURN(rval);
+}
+
+int EGLPNUM_TYPENAME_ILLprice_get_price (
+ EGLPNUM_TYPENAME_price_info * const p,
+ int const phase)
+{
+ int pri = -1;
+
+ switch (phase)
+ {
+ case PRIMAL_PHASEI:
+ return p->pI_price;
+ case PRIMAL_PHASEII:
+ return p->pII_price;
+ case DUAL_PHASEI:
+ return p->dI_price;
+ case DUAL_PHASEII:
+ return p->dII_price;
+ }
+ return pri;
+}
+
+void EGLPNUM_TYPENAME_ILLprice_free_mpartial_info (
+ EGLPNUM_TYPENAME_mpart_info * p)
+{
+ ILL_IFFREE (p->gstart, int);
+ ILL_IFFREE (p->gshift, int);
+ ILL_IFFREE (p->gsize, int);
+ ILL_IFFREE (p->bucket, int);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (p->infeas);
+ ILL_IFFREE (p->perm, int);
+}
+
+int EGLPNUM_TYPENAME_ILLprice_build_mpartial_info (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_price_info * const pinf,
+ int const pricetype)
+{
+ int i = 0;
+ int rval = 0;
+ int extra = 0;
+ int nelems;
+ EGLPNUM_TYPENAME_mpart_info *p;
+
+ p = (pricetype == COL_PRICING) ? &(pinf->pmpinfo) : &(pinf->dmpinfo);
+ p->k = 50;
+ p->cgroup = 0;
+ nelems = (pricetype == COL_PRICING) ? lp->nnbasic : lp->nrows;
+
+ if (nelems % p->k)
+ extra = nelems - p->k * (nelems / p->k);
+ p->ngroups = nelems / p->k;
+ if (extra != 0)
+ p->ngroups++;
+
+ ILL_SAFE_MALLOC (p->gstart, p->ngroups, int);
+ ILL_SAFE_MALLOC (p->gshift, p->ngroups, int);
+ ILL_SAFE_MALLOC (p->gsize, p->ngroups, int);
+ ILL_SAFE_MALLOC (p->bucket, 2 * p->k, int);
+ p->infeas = EGLPNUM_TYPENAME_EGlpNumAllocArray (2 * p->k);
+ ILL_SAFE_MALLOC (p->perm, 2 * p->k, int);
+
+ p->bsize = 0;
+
+ if (extra != 0)
+ {
+ p->gstart[0] = 0;
+ p->gshift[0] = 1;
+ p->gsize[0] = extra;
+ for (i = 1; i < p->ngroups; i++)
+ {
+ p->gstart[i] = extra + i - 1;
+ p->gshift[i] = p->ngroups - 1;
+ p->gsize[i] = p->k;
+ }
+ }
+ else
+ {
+ for (i = 0; i < p->ngroups; i++)
+ {
+ p->gstart[i] = i;
+ p->gshift[i] = p->ngroups;
+ p->gsize[i] = p->k;
+ }
+ }
+
+CLEANUP:
+ if (rval)
+ EGLPNUM_TYPENAME_ILLprice_free_mpartial_info (p);
+ EG_RETURN(rval);
+}
+
+void EGLPNUM_TYPENAME_ILLprice_init_mpartial_price (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_price_info * const pinf,
+ int const phase,
+ int const pricetype)
+{
+ int i;
+ EGLPNUM_TYPENAME_mpart_info *p;
+
+ p = (pricetype == COL_PRICING) ? &(pinf->pmpinfo) : &(pinf->dmpinfo);
+ p->bsize = 0;
+ i = p->cgroup;
+ do
+ {
+ EGLPNUM_TYPENAME_ILLprice_mpartial_group (lp, p, phase, i, pricetype);
+ i = (i + 1) % p->ngroups;
+ } while (i != p->cgroup && p->bsize <= p->k);
+ p->cgroup = i;
+}
+
+void EGLPNUM_TYPENAME_ILLprice_update_mpartial_price (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_price_info * const pinf,
+ int const phase,
+ int const pricetype)
+{
+ int i = 0;
+ int csize = 0;
+ EGLPNUM_TYPE infeas;
+ EGLPNUM_TYPENAME_mpart_info *p;
+ EGLPNUM_TYPENAME_price_res pr;
+
+ p = (pricetype == COL_PRICING) ? &(pinf->pmpinfo) : &(pinf->dmpinfo);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (pr.dinfeas);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (pr.pinfeas);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (infeas);
+
+#ifdef MULTIP
+ i = 0;
+ while (i < p->bsize)
+ {
+ if (pricetype == COL_PRICING)
+ {
+ EGLPNUM_TYPENAME_ILLprice_column (lp, p->bucket[i], phase, &pr);
+ EGLPNUM_TYPENAME_EGlpNumCopy (infeas, pr.dinfeas);
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_ILLprice_row (lp, p->bucket[i], phase, &pr);
+ EGLPNUM_TYPENAME_EGlpNumCopy (infeas, pr.pinfeas);
+ }
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (infeas))
+ {
+ p->bucket[i] = p->bucket[p->bsize - 1];
+ p->bsize--;
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (p->infeas[i], infeas);
+ i++;
+ }
+ }
+ if (p->bsize > 0)
+ {
+ for (i = 0; i < p->bsize; i++)
+ p->perm[i] = i;
+ EGLPNUM_TYPENAME_EGutilPermSort ((size_t) (p->bsize), p->perm,
+ (const EGLPNUM_TYPE * const) p->infeas);
+
+ csize = QSMIN (p->bsize, p->k);
+ for (i = csize - 1; i >= 0; i--)
+ lp->iwork[p->bucket[p->perm[i]]] = 1;
+
+ for (i = 0, csize = 0; i < p->bsize; i++)
+ if (lp->iwork[p->bucket[i]] == 1)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (p->infeas[csize], p->infeas[i]);
+ p->bucket[csize] = p->bucket[i];
+ csize++;
+ }
+ p->bsize = csize;
+ }
+#else
+ p->bsize = 0;
+#endif
+
+ i = p->cgroup;
+ do
+ {
+ EGLPNUM_TYPENAME_ILLprice_mpartial_group (lp, p, phase, i, pricetype);
+ i = (i + 1) % p->ngroups;
+ } while (i != p->cgroup && p->bsize <= p->k);
+ p->cgroup = i;
+
+#ifdef MULTIP
+ for (i = 0; i < csize; i++)
+ lp->iwork[p->bucket[i]] = 0;
+#endif
+ EGLPNUM_TYPENAME_EGlpNumClearVar (infeas);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (pr.pinfeas);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (pr.dinfeas);
+}
+
+void EGLPNUM_TYPENAME_ILLprice_delete_onempart_price (
+ /*EGLPNUM_TYPENAME_lpinfo * const lp,*/
+ EGLPNUM_TYPENAME_price_info * const pinf,
+ int const indx,
+ int const pricetype)
+{
+ int i = 0;
+ EGLPNUM_TYPENAME_mpart_info *p;
+
+ p = (pricetype == COL_PRICING) ? &(pinf->pmpinfo) : &(pinf->dmpinfo);
+
+ for (i = 0; i < p->bsize; i++)
+ if (p->bucket[i] == indx)
+ {
+ p->bucket[i] = p->bucket[p->bsize - 1];
+ EGLPNUM_TYPENAME_EGlpNumCopy (p->infeas[i], p->infeas[p->bsize - 1]);
+ p->bsize--;
+ break;
+ }
+}
+
+void EGLPNUM_TYPENAME_ILLprice_mpartial_group (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_mpart_info * const p,
+ int const phase,
+ int const g,
+ int const pricetype)
+{
+ int i, ix;
+ int gstart = p->gstart[g];
+ int gsize = p->gsize[g];
+ int gshift = p->gshift[g];
+ EGLPNUM_TYPE infeas;
+ EGLPNUM_TYPENAME_price_res pr;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (pr.dinfeas);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (pr.pinfeas);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (infeas);
+
+ for (i = 0, ix = gstart; i < gsize; i++, ix += gshift)
+ {
+#ifdef MULTIP
+ if (lp->iwork[ix])
+ continue;
+#endif
+ if (pricetype == COL_PRICING)
+ {
+ EGLPNUM_TYPENAME_ILLprice_column (lp, ix, phase, &pr);
+ EGLPNUM_TYPENAME_EGlpNumCopy (infeas, pr.dinfeas);
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_ILLprice_row (lp, ix, phase, &pr);
+ EGLPNUM_TYPENAME_EGlpNumCopy (infeas, pr.pinfeas);
+ }
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (infeas))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (p->infeas[p->bsize], infeas);
+ p->bucket[p->bsize] = ix;
+ p->bsize++;
+ }
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (infeas);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (pr.dinfeas);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (pr.pinfeas);
+}
+
+void EGLPNUM_TYPENAME_ILLprice_column (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ int const ix,
+ int const phase,
+ EGLPNUM_TYPENAME_price_res * const pr)
+{
+ int i;
+ int col;
+ int mcnt;
+ int mbeg;
+ EGLPNUM_TYPE sum;
+
+ EGLPNUM_TYPENAME_EGlpNumZero (pr->dinfeas);
+ col = lp->nbaz[ix];
+ if (lp->vtype[col] == VARTIFICIAL || lp->vtype[col] == VFIXED)
+ return;
+ EGLPNUM_TYPENAME_EGlpNumInitVar (sum);
+ EGLPNUM_TYPENAME_EGlpNumZero (sum);
+ mcnt = lp->matcnt[col];
+ mbeg = lp->matbeg[col];
+
+ if (phase == PRIMAL_PHASEII)
+ {
+ for (i = 0; i < mcnt; i++)
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, lp->piz[lp->matind[mbeg + i]], lp->matval[mbeg + i]);
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (lp->dz[ix], lp->cz[col], sum);
+ compute_dualII_inf (lp, ix, &(pr->dinfeas));
+ }
+ else
+ {
+ for (i = 0; i < mcnt; i++)
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, lp->pIpiz[lp->matind[mbeg + i]], lp->matval[mbeg + i]);
+ EGLPNUM_TYPENAME_EGlpNumCopyNeg (lp->pIdz[ix], sum);
+ compute_dualI_inf (lp, ix, &(pr->dinfeas));
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (sum);
+}
+
+void EGLPNUM_TYPENAME_ILLprice_row (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ int const ix,
+ int const phase,
+ EGLPNUM_TYPENAME_price_res * const pr)
+{
+ if (phase == DUAL_PHASEII)
+ compute_primalII_inf (lp, ix, &(pr->pinfeas));
+ else
+ compute_primalI_inf (lp, ix, &(pr->pinfeas));
+}
+
+int EGLPNUM_TYPENAME_ILLprice_build_pdevex_norms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_p_devex_info * const pdinfo,
+ int const reinit)
+{
+ int j;
+ int rval = 0;
+
+ if (reinit == 0)
+ {
+ pdinfo->ninit = 0;
+ pdinfo->norms = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nnbasic);
+ ILL_SAFE_MALLOC (pdinfo->refframe, lp->ncols, int);
+ }
+
+ if (reinit != 0)
+ pdinfo->ninit++;
+
+ for (j = 0; j < lp->ncols; j++)
+ {
+ if (lp->vstat[j] == STAT_BASIC)
+ pdinfo->refframe[j] = 0;
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumOne (pdinfo->norms[lp->vindex[j]]);
+ pdinfo->refframe[j] = 1;
+ }
+ }
+
+CLEANUP:
+ if (rval)
+ {
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (pdinfo->norms);
+ ILL_IFFREE (pdinfo->refframe, int);
+ }
+ EG_RETURN(rval);
+}
+
+int EGLPNUM_TYPENAME_ILLprice_update_pdevex_norms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_p_devex_info * const pdinfo,
+ int const eindex,
+ EGLPNUM_TYPE yl)
+{
+ int i, j;
+ EGLPNUM_TYPE normj;
+ EGLPNUM_TYPE zAj;
+ EGLPNUM_TYPE ntmp, ntmp2;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (normj);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (zAj);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (ntmp);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (ntmp2);
+ EGLPNUM_TYPENAME_EGlpNumZero (normj);
+
+ for (i = 0; i < lp->yjz.nzcnt; i++)
+ if (pdinfo->refframe[lp->baz[lp->yjz.indx[i]]])
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (normj, lp->yjz.coef[i], lp->yjz.coef[i]);
+
+ if (pdinfo->refframe[lp->nbaz[eindex]])
+ EGLPNUM_TYPENAME_EGlpNumAddTo (normj, EGLPNUM_TYPENAME_oneLpNum);
+
+ EGLPNUM_TYPENAME_EGlpNumSet(ntmp,1000.0);
+ EGLPNUM_TYPENAME_EGlpNumSet(ntmp2,0.001);
+ EGLPNUM_TYPENAME_EGlpNumMultTo(ntmp,pdinfo->norms[eindex]);
+ EGLPNUM_TYPENAME_EGlpNumMultTo(ntmp2,pdinfo->norms[eindex]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (normj, ntmp2) || EGLPNUM_TYPENAME_EGlpNumIsLess (ntmp, normj))
+ {
+ EGLPNUM_TYPENAME_EGlpNumClearVar (zAj);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (normj);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp2);
+ return EGLPNUM_TYPENAME_ILLprice_build_pdevex_norms (lp, pdinfo, 1);
+ }
+
+ for (i = 0; i < lp->zA.nzcnt; i++)
+ {
+ j = lp->zA.indx[i];
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (zAj, lp->zA.coef[i], yl);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (zAj, zAj);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (zAj, normj);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (pdinfo->norms[j], zAj))
+ EGLPNUM_TYPENAME_EGlpNumCopy (pdinfo->norms[j], zAj);
+ }
+ EGLPNUM_TYPENAME_EGlpNumDivTo (normj, yl);
+ EGLPNUM_TYPENAME_EGlpNumDivTo (normj, yl);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (normj, EGLPNUM_TYPENAME_oneLpNum))
+ EGLPNUM_TYPENAME_EGlpNumCopy (pdinfo->norms[eindex], EGLPNUM_TYPENAME_oneLpNum);
+ else
+ EGLPNUM_TYPENAME_EGlpNumCopy (pdinfo->norms[eindex], normj);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (zAj);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (normj);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp2);
+ return 0;
+}
+
+int EGLPNUM_TYPENAME_ILLprice_build_psteep_norms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_p_steep_info * const psinfo)
+{
+ int j;
+ int rval = 0;
+ EGLPNUM_TYPENAME_svector yz;
+
+ EGLPNUM_TYPENAME_ILLsvector_init (&yz);
+ rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&yz, lp->nrows);
+ CHECKRVALG(rval,CLEANUP);
+ psinfo->norms = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nnbasic);
+
+ for (j = 0; j < lp->nnbasic; j++)
+ {
+ rval = ILLstring_report (NULL, &lp->O->reporter);
+ CHECKRVALG(rval,CLEANUP);
+ EGLPNUM_TYPENAME_ILLfct_compute_yz (lp, &yz, 0, lp->nbaz[j]);
+ EGLPNUM_TYPENAME_EGlpNumInnProd (psinfo->norms[j], yz.coef, yz.coef, (size_t) yz.nzcnt);
+ EGLPNUM_TYPENAME_EGlpNumAddTo (psinfo->norms[j], EGLPNUM_TYPENAME_oneLpNum);
+ }
+
+CLEANUP:
+ EGLPNUM_TYPENAME_ILLsvector_free (&yz);
+ if (rval)
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (psinfo->norms);
+
+ EG_RETURN(rval);
+}
+
+void EGLPNUM_TYPENAME_ILLprice_update_psteep_norms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_p_steep_info * const psinfo,
+ EGLPNUM_TYPENAME_svector * const wz,
+ int const eindex,
+ EGLPNUM_TYPE yl)
+{
+ int i, j, k;
+ int mcnt, mbeg;
+ EGLPNUM_TYPE normj,ntmp;
+ EGLPNUM_TYPE zAj, wAj;
+ EGLPNUM_TYPE *v = 0;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (normj);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (zAj);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (ntmp);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (wAj);
+ EGLPNUM_TYPENAME_EGlpNumInnProd (normj, lp->yjz.coef, lp->yjz.coef, (size_t) (lp->yjz.nzcnt));
+ EGLPNUM_TYPENAME_EGlpNumAddTo (normj, EGLPNUM_TYPENAME_oneLpNum);
+
+#if 0
+ Bico - remove warnings for dist
+ if (fabs ((normj - psinfo->norms[eindex]) / normj) > 1000.0 /* 0.01 */ )
+ {
+ QSlog("warning: incorrect norm values");
+ QSlog("anorm = %.6f, pnorm = %.6f", normj, psinfo->norms[eindex]);
+ }
+#endif
+
+ EGLPNUM_TYPENAME_ILLfct_load_workvector (lp, wz);
+ v = lp->work.coef;
+
+ for (k = 0; k < lp->zA.nzcnt; k++)
+ {
+ j = lp->zA.indx[k];
+ EGLPNUM_TYPENAME_EGlpNumCopy (zAj, lp->zA.coef[k]);
+ EGLPNUM_TYPENAME_EGlpNumZero (wAj);
+ mcnt = lp->matcnt[lp->nbaz[j]];
+ mbeg = lp->matbeg[lp->nbaz[j]];
+ for (i = 0; i < mcnt; i++)
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (wAj, lp->matval[mbeg + i], v[lp->matind[mbeg + i]]);
+
+ /* compute ntmp = (zAj * ((zAj * normj / yl) - (2.0 * wAj))) / yl; */
+ EGLPNUM_TYPENAME_EGlpNumCopy(ntmp,zAj);
+ EGLPNUM_TYPENAME_EGlpNumMultTo(ntmp,normj);
+ EGLPNUM_TYPENAME_EGlpNumDivTo(ntmp,yl);
+ EGLPNUM_TYPENAME_EGlpNumSubTo(ntmp,wAj);
+ EGLPNUM_TYPENAME_EGlpNumSubTo(ntmp,wAj);
+ EGLPNUM_TYPENAME_EGlpNumMultTo(ntmp,zAj);
+ EGLPNUM_TYPENAME_EGlpNumDivTo(ntmp,yl);
+ /* set psinfo->norms[j] += (zAj * ((zAj * normj / yl) - (2.0 * wAj))) / yl; */
+ EGLPNUM_TYPENAME_EGlpNumAddTo(psinfo->norms[j],ntmp);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (psinfo->norms[j], EGLPNUM_TYPENAME_oneLpNum))
+ EGLPNUM_TYPENAME_EGlpNumOne (psinfo->norms[j]);
+ }
+
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (psinfo->norms[eindex], normj, yl);
+ EGLPNUM_TYPENAME_EGlpNumDivTo (psinfo->norms[eindex], yl);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (psinfo->norms[eindex], EGLPNUM_TYPENAME_oneLpNum))
+ EGLPNUM_TYPENAME_EGlpNumOne (psinfo->norms[eindex]);
+
+ EGLPNUM_TYPENAME_ILLfct_zero_workvector (lp);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (wAj);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (zAj);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (normj);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+}
+
+int EGLPNUM_TYPENAME_ILLprice_build_ddevex_norms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_d_devex_info * const ddinfo,
+ int const reinit)
+{
+ int i;
+ int rval = 0;
+
+ if (reinit == 0)
+ {
+ ddinfo->ninit = 0;
+ ddinfo->norms = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+ ILL_SAFE_MALLOC (ddinfo->refframe, lp->ncols, int);
+ }
+ if (reinit != 0)
+ ddinfo->ninit++;
+
+ for (i = 0; i < lp->ncols; i++)
+ ddinfo->refframe[i] = (lp->vstat[i] == STAT_BASIC) ? 1 : 0;
+
+ for (i = 0; i < lp->nrows; i++)
+ EGLPNUM_TYPENAME_EGlpNumOne (ddinfo->norms[i]);
+
+CLEANUP:
+ if (rval)
+ {
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (ddinfo->norms);
+ ILL_IFFREE (ddinfo->refframe, int);
+ }
+ EG_RETURN(rval);
+}
+
+int EGLPNUM_TYPENAME_ILLprice_update_ddevex_norms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_d_devex_info * const ddinfo,
+ int const lindex,
+ EGLPNUM_TYPE yl)
+{
+ int i, r;
+ EGLPNUM_TYPE normi;
+ EGLPNUM_TYPE yr;
+ EGLPNUM_TYPE ntmp,ntmp2;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (ntmp);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (ntmp2);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (normi);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (yr);
+ EGLPNUM_TYPENAME_EGlpNumZero (normi);
+
+ for (i = 0; i < lp->zA.nzcnt; i++)
+ if (ddinfo->refframe[lp->nbaz[lp->zA.indx[i]]])
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (normi, lp->zA.coef[i], lp->zA.coef[i]);
+
+ if (ddinfo->refframe[lp->baz[lindex]])
+ EGLPNUM_TYPENAME_EGlpNumAddTo (normi, EGLPNUM_TYPENAME_oneLpNum);
+
+ EGLPNUM_TYPENAME_EGlpNumSet(ntmp,1000.0);
+ EGLPNUM_TYPENAME_EGlpNumSet(ntmp2,0.001);
+ EGLPNUM_TYPENAME_EGlpNumMultTo(ntmp,ddinfo->norms[lindex]);
+ EGLPNUM_TYPENAME_EGlpNumMultTo(ntmp2,ddinfo->norms[lindex]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess(normi, ntmp2) || EGLPNUM_TYPENAME_EGlpNumIsLess(ntmp, normi))
+ {
+ EGLPNUM_TYPENAME_EGlpNumClearVar (normi);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (yr);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp2);
+ return EGLPNUM_TYPENAME_ILLprice_build_ddevex_norms (lp, ddinfo, 1);
+ }
+
+ for (i = 0; i < lp->yjz.nzcnt; i++)
+ {
+ r = lp->yjz.indx[i];
+ EGLPNUM_TYPENAME_EGlpNumCopy(yr, lp->yjz.coef[i]);
+ EGLPNUM_TYPENAME_EGlpNumCopy(ntmp,yr);
+ EGLPNUM_TYPENAME_EGlpNumMultTo(ntmp,yr);
+ EGLPNUM_TYPENAME_EGlpNumMultTo(ntmp,normi);
+ EGLPNUM_TYPENAME_EGlpNumDivTo(ntmp,yl);
+ EGLPNUM_TYPENAME_EGlpNumDivTo(ntmp,yl);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (ddinfo->norms[r], ntmp))
+ EGLPNUM_TYPENAME_EGlpNumCopy (ddinfo->norms[r], ntmp);
+ }
+ EGLPNUM_TYPENAME_EGlpNumCopy (ddinfo->norms[lindex], normi);
+ EGLPNUM_TYPENAME_EGlpNumDivTo(ddinfo->norms[lindex], yl);
+ EGLPNUM_TYPENAME_EGlpNumDivTo(ddinfo->norms[lindex], yl);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (ddinfo->norms[lindex], EGLPNUM_TYPENAME_oneLpNum))
+ EGLPNUM_TYPENAME_EGlpNumOne (ddinfo->norms[lindex]);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (normi);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (yr);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp2);
+ return 0;
+}
+
+int EGLPNUM_TYPENAME_ILLprice_build_dsteep_norms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_d_steep_info * const dsinfo)
+{
+ int i;
+ int rval = 0;
+ EGLPNUM_TYPENAME_svector z;
+
+ EGLPNUM_TYPENAME_ILLsvector_init (&z);
+ rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&z, lp->nrows);
+ CHECKRVALG(rval,CLEANUP);
+ dsinfo->norms = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+
+ for (i = 0; i < lp->nrows; i++)
+ {
+ rval = ILLstring_report (NULL, &lp->O->reporter);
+ CHECKRVALG(rval,CLEANUP);
+
+ EGLPNUM_TYPENAME_ILLfct_compute_zz (lp, &z, i);
+
+ EGLPNUM_TYPENAME_EGlpNumInnProd (dsinfo->norms[i], z.coef, z.coef, (size_t) z.nzcnt);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (dsinfo->norms[i], EGLPNUM_TYPENAME_PARAM_MIN_DNORM))
+ EGLPNUM_TYPENAME_EGlpNumCopy (dsinfo->norms[i], EGLPNUM_TYPENAME_PARAM_MIN_DNORM);
+ }
+
+CLEANUP:
+ EGLPNUM_TYPENAME_ILLsvector_free (&z);
+ if (rval)
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (dsinfo->norms);
+
+ EG_RETURN(rval);
+}
+
+int EGLPNUM_TYPENAME_ILLprice_get_dsteep_norms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ int const count,
+ int *const rowind,
+ EGLPNUM_TYPE * const norms)
+{
+ int i;
+ int rval = 0;
+ EGLPNUM_TYPENAME_svector z;
+
+ EGLPNUM_TYPENAME_ILLsvector_init (&z);
+ rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&z, lp->nrows);
+ CHECKRVALG(rval,CLEANUP);
+
+ for (i = 0; i < count; i++)
+ {
+ EGLPNUM_TYPENAME_ILLfct_compute_zz (lp, &z, rowind[i]);
+ EGLPNUM_TYPENAME_EGlpNumInnProd (norms[i], z.coef, z.coef, (size_t) z.nzcnt);
+ }
+
+CLEANUP:
+ EGLPNUM_TYPENAME_ILLsvector_free (&z);
+ EG_RETURN(rval);
+}
+
+void EGLPNUM_TYPENAME_ILLprice_update_dsteep_norms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_d_steep_info * const dsinfo,
+ EGLPNUM_TYPENAME_svector * const wz,
+ int const lindex,
+ EGLPNUM_TYPE yl)
+{
+ int i, k;
+ EGLPNUM_TYPE yij;
+ EGLPNUM_TYPE norml;
+ EGLPNUM_TYPE *v = 0;
+ EGLPNUM_TYPE ntmp;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (ntmp);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (norml);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (yij);
+ EGLPNUM_TYPENAME_EGlpNumInnProd (norml, lp->zz.coef, lp->zz.coef, (size_t) (lp->zz.nzcnt));
+
+#if 0
+ Bico - remove warnings for dist
+ if (fabs ((norml - dsinfo->norms[lindex]) / norml) > 1000.0 /*0.01 */ )
+ {
+ QSlog("warning: incorrect dnorm values");
+ QSlog("anorm = %.6f, pnorm = %.6f", norml, dsinfo->norms[lindex]);
+ }
+#endif
+
+ EGLPNUM_TYPENAME_ILLfct_load_workvector (lp, wz);
+ v = lp->work.coef;
+
+ for (k = 0; k < lp->yjz.nzcnt; k++)
+ {
+ i = lp->yjz.indx[k];
+ EGLPNUM_TYPENAME_EGlpNumCopy (yij, lp->yjz.coef[k]);
+ /* compute in ntmp (yij * ((yij * norml / yl) - (2.0 * v[i]))) / yl; */
+ EGLPNUM_TYPENAME_EGlpNumCopy(ntmp,yij);
+ EGLPNUM_TYPENAME_EGlpNumMultTo(ntmp,norml);
+ EGLPNUM_TYPENAME_EGlpNumDivTo(ntmp,yl);
+ EGLPNUM_TYPENAME_EGlpNumSubTo(ntmp,v[i]);
+ EGLPNUM_TYPENAME_EGlpNumSubTo(ntmp,v[i]);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (ntmp, yij);
+ EGLPNUM_TYPENAME_EGlpNumDivTo (ntmp, yl);
+ /* set dsinfo->norms[i] += (yij * ((yij * norml / yl) - (2.0 * v[i]))) / yl;*/
+ EGLPNUM_TYPENAME_EGlpNumAddTo(dsinfo->norms[i], ntmp);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (dsinfo->norms[i], EGLPNUM_TYPENAME_PARAM_MIN_DNORM))
+ EGLPNUM_TYPENAME_EGlpNumCopy (dsinfo->norms[i], EGLPNUM_TYPENAME_PARAM_MIN_DNORM);
+ }
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (dsinfo->norms[lindex], norml, yl);
+ EGLPNUM_TYPENAME_EGlpNumDivTo (dsinfo->norms[lindex], yl);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (dsinfo->norms[lindex], EGLPNUM_TYPENAME_PARAM_MIN_DNORM))
+ EGLPNUM_TYPENAME_EGlpNumCopy (dsinfo->norms[lindex], EGLPNUM_TYPENAME_PARAM_MIN_DNORM);
+
+ EGLPNUM_TYPENAME_ILLfct_zero_workvector (lp);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (norml);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (yij);
+}
+
+static void update_d_scaleinf (
+ EGLPNUM_TYPENAME_price_info * const p,
+ EGLPNUM_TYPENAME_heap * const h,
+ int const j,
+ EGLPNUM_TYPE inf,
+ int const prule)
+{
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (inf))
+ {
+ EGLPNUM_TYPENAME_EGlpNumZero (p->d_scaleinf[j]);
+ if (h->hexist != 0 && h->loc[j] != -1)
+ EGLPNUM_TYPENAME_ILLheap_delete (h, j);
+ }
+ else
+ {
+ if (prule == QS_PRICE_PDANTZIG)
+ EGLPNUM_TYPENAME_EGlpNumCopy (p->d_scaleinf[j], inf);
+ else if (prule == QS_PRICE_PDEVEX)
+ EGLPNUM_TYPENAME_EGlpNumCopySqrOver (p->d_scaleinf[j], inf, p->pdinfo.norms[j]);
+ else if (prule == QS_PRICE_PSTEEP)
+ EGLPNUM_TYPENAME_EGlpNumCopySqrOver (p->d_scaleinf[j], inf, p->psinfo.norms[j]);
+
+ if (h->hexist != 0)
+ {
+ if (h->loc[j] == -1)
+ EGLPNUM_TYPENAME_ILLheap_insert (h, j);
+ else
+ EGLPNUM_TYPENAME_ILLheap_modify (h, j);
+ }
+ }
+}
+
+static void compute_dualI_inf (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ const int j,
+ EGLPNUM_TYPE * const inf)
+{
+ int col = lp->nbaz[j];
+ int vt = lp->vtype[col];
+ int vs = lp->vstat[col];
+ EGLPNUM_TYPE*dj = &(lp->pIdz[j]);
+ EGLPNUM_TYPE*ftol = &(lp->tol->id_tol);
+ EGLPNUM_TYPENAME_EGlpNumZero (*inf);
+ if (vt != VARTIFICIAL && vt != VFIXED)
+ {
+ if( EGLPNUM_TYPENAME_EGlpNumIsSumLess(*dj,*ftol,EGLPNUM_TYPENAME_zeroLpNum) && (vs == STAT_LOWER || vs == STAT_ZERO))
+ EGLPNUM_TYPENAME_EGlpNumCopyNeg(*inf,*dj);
+ else if (EGLPNUM_TYPENAME_EGlpNumIsLess(*ftol, *dj) && (vs == STAT_UPPER || vs == STAT_ZERO))
+ EGLPNUM_TYPENAME_EGlpNumCopy (*inf, *dj);
+ }
+}
+
+static void compute_dualII_inf (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ int const j,
+ EGLPNUM_TYPE * const inf)
+{
+ int col = lp->nbaz[j];
+ int vt = lp->vtype[col];
+ int vs = lp->vstat[col];
+ EGLPNUM_TYPE*dj = &(lp->dz[j]);
+ EGLPNUM_TYPE*ftol = &(lp->tol->dfeas_tol);
+ EGLPNUM_TYPENAME_EGlpNumZero (*inf);
+ if (vt != VARTIFICIAL && vt != VFIXED)
+ {
+ if( EGLPNUM_TYPENAME_EGlpNumIsSumLess(*dj,*ftol,EGLPNUM_TYPENAME_zeroLpNum) && (vs == STAT_LOWER || vs == STAT_ZERO))
+ EGLPNUM_TYPENAME_EGlpNumCopyNeg(*inf,*dj);
+ else if (EGLPNUM_TYPENAME_EGlpNumIsLess(*ftol,*dj) && (vs == STAT_UPPER || vs == STAT_ZERO))
+ EGLPNUM_TYPENAME_EGlpNumCopy (*inf, *dj);
+ }
+}
+
+void EGLPNUM_TYPENAME_ILLprice_compute_dual_inf (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_price_info * const p,
+ int *const ix,
+ int const icnt,
+ int const phase)
+{
+ int i;
+ int price;
+ EGLPNUM_TYPE inf;
+ EGLPNUM_TYPENAME_heap *h = &(p->h);
+
+ price = (phase == PRIMAL_PHASEI) ? p->pI_price : p->pII_price;
+ EGLPNUM_TYPENAME_EGlpNumInitVar (inf);
+ EGLPNUM_TYPENAME_EGlpNumZero (inf);
+
+ if (phase == PRIMAL_PHASEI)
+ {
+ if (ix == NULL)
+ for (i = 0; i < lp->nnbasic; i++)
+ {
+ compute_dualI_inf (lp, i, &(inf));
+ update_d_scaleinf (p, h, i, inf, price);
+ }
+ else
+ for (i = 0; i < icnt; i++)
+ {
+ compute_dualI_inf (lp, ix[i], &(inf));
+ update_d_scaleinf (p, h, ix[i], inf, price);
+ }
+ }
+ else if (phase == PRIMAL_PHASEII)
+ {
+ if (ix == NULL)
+ for (i = 0; i < lp->nnbasic; i++)
+ {
+ compute_dualII_inf (lp, i, &inf);
+ update_d_scaleinf (p, h, i, inf, price);
+ }
+ else
+ for (i = 0; i < icnt; i++)
+ {
+ compute_dualII_inf (lp, ix[i], &inf);
+ update_d_scaleinf (p, h, ix[i], inf, price);
+ }
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (inf);
+}
+
+void EGLPNUM_TYPENAME_ILLprice_primal (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_price_info * const pinf,
+ EGLPNUM_TYPENAME_price_res * const pr,
+ int const phase)
+{
+ int j, vs;
+ EGLPNUM_TYPE d_e, d_max;
+ EGLPNUM_TYPE *ftol = &(lp->tol->dfeas_tol);
+ EGLPNUM_TYPENAME_heap *const h = &(pinf->h);
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (d_e);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (d_max);
+ pr->eindex = -1;
+ EGLPNUM_TYPENAME_EGlpNumZero(d_max);
+
+#if USEHEAP > 0
+ EGLPNUM_TYPENAME_ILLprice_test_for_heap (lp, pinf, lp->nnbasic, pinf->d_scaleinf,
+ PRIMAL_SIMPLEX, 1);
+#endif
+
+ if (pinf->p_strategy == COMPLETE_PRICING)
+ {
+ if (h->hexist)
+ {
+ pr->eindex = EGLPNUM_TYPENAME_ILLheap_findmin (h);
+ if (pr->eindex != -1)
+ EGLPNUM_TYPENAME_ILLheap_delete (h, pr->eindex);
+ }
+ else
+ {
+ for (j = 0; j < lp->nnbasic; j++)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (d_max, pinf->d_scaleinf[j]))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (d_max, pinf->d_scaleinf[j]);
+ pr->eindex = j;
+ }
+ }
+ }
+ }
+ else if (pinf->p_strategy == MULTI_PART_PRICING)
+ {
+ for (j = 0; j < pinf->pmpinfo.bsize; j++)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (d_max, pinf->pmpinfo.infeas[j]))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (d_max, pinf->pmpinfo.infeas[j]);
+ pr->eindex = pinf->pmpinfo.bucket[j];
+ }
+ }
+ }
+
+ if (pr->eindex < 0)
+ pr->price_stat = PRICE_OPTIMAL;
+ else
+ {
+ if (phase == PRIMAL_PHASEI)
+ EGLPNUM_TYPENAME_EGlpNumCopy (d_e, lp->pIdz[pr->eindex]);
+ else
+ EGLPNUM_TYPENAME_EGlpNumCopy (d_e, lp->dz[pr->eindex]);
+ vs = lp->vstat[lp->nbaz[pr->eindex]];
+
+ pr->price_stat = PRICE_NONOPTIMAL;
+ if (vs == STAT_UPPER || (vs == STAT_ZERO && EGLPNUM_TYPENAME_EGlpNumIsLess (*ftol, d_e)))
+ pr->dir = VDECREASE;
+ else
+ pr->dir = VINCREASE;
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (d_e);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (d_max);
+}
+
+static void update_p_scaleinf (
+ EGLPNUM_TYPENAME_price_info * const p,
+ EGLPNUM_TYPENAME_heap * const h,
+ int const i,
+ EGLPNUM_TYPE inf,
+ int const prule)
+{
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (inf))
+ {
+ EGLPNUM_TYPENAME_EGlpNumZero (p->p_scaleinf[i]);
+ if (h->hexist != 0 && h->loc[i] != -1)
+ EGLPNUM_TYPENAME_ILLheap_delete (h, i);
+ }
+ else
+ {
+ if (prule == QS_PRICE_DDANTZIG)
+ EGLPNUM_TYPENAME_EGlpNumCopy (p->p_scaleinf[i], inf);
+ else if (prule == QS_PRICE_DSTEEP)
+ EGLPNUM_TYPENAME_EGlpNumCopySqrOver (p->p_scaleinf[i], inf, p->dsinfo.norms[i]);
+ else if (prule == QS_PRICE_DDEVEX)
+ EGLPNUM_TYPENAME_EGlpNumCopySqrOver (p->p_scaleinf[i], inf, p->ddinfo.norms[i]);
+
+ if (h->hexist != 0)
+ {
+ if (h->loc[i] == -1)
+ EGLPNUM_TYPENAME_ILLheap_insert (h, i);
+ else
+ EGLPNUM_TYPENAME_ILLheap_modify (h, i);
+ }
+ }
+}
+
+static void compute_primalI_inf (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ int const i,
+ EGLPNUM_TYPE * const inf)
+{
+ int const col = lp->baz[i];
+ EGLPNUM_TYPE*x = &(lp->xbz[i]);
+ EGLPNUM_TYPE*l = &(lp->lz[col]);
+ EGLPNUM_TYPE*u = &(lp->uz[col]);
+ EGLPNUM_TYPE*ftol = &(lp->tol->ip_tol);
+ EGLPNUM_TYPENAME_EGlpNumZero (*inf);
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (*ftol, *x) && EGLPNUM_TYPENAME_EGlpNumIsNeqq (*u, EGLPNUM_TYPENAME_INFTY))
+ EGLPNUM_TYPENAME_EGlpNumCopy (*inf, *x);
+ else if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*l, EGLPNUM_TYPENAME_NINFTY) && EGLPNUM_TYPENAME_EGlpNumIsSumLess (*x, *ftol,EGLPNUM_TYPENAME_zeroLpNum))
+ EGLPNUM_TYPENAME_EGlpNumCopy (*inf, *x);
+}
+
+static void compute_primalII_inf (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ int const i,
+ EGLPNUM_TYPE * const inf)
+{
+ int const col = lp->baz[i];
+ EGLPNUM_TYPE*x = &(lp->xbz[i]);
+ EGLPNUM_TYPE*l = &(lp->lz[col]);
+ EGLPNUM_TYPE*u = &(lp->uz[col]);
+ EGLPNUM_TYPE*ftol = &(lp->tol->pfeas_tol);
+ EGLPNUM_TYPENAME_EGlpNumZero (*inf);
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*u, EGLPNUM_TYPENAME_INFTY) && EGLPNUM_TYPENAME_EGlpNumIsSumLess (*u, *ftol, *x))
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (*inf, *x, *u);
+ else if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*l, EGLPNUM_TYPENAME_NINFTY) && EGLPNUM_TYPENAME_EGlpNumIsSumLess (*x, *ftol, *l))
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (*inf, *l, *x);
+}
+
+void EGLPNUM_TYPENAME_ILLprice_compute_primal_inf (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_price_info * const p,
+ int *const ix,
+ int const icnt,
+ int const phase)
+{
+ int i;
+ int price;
+ EGLPNUM_TYPE inf;
+ EGLPNUM_TYPENAME_heap *h = &(p->h);
+
+ price = (phase == DUAL_PHASEI) ? p->dI_price : p->dII_price;
+ EGLPNUM_TYPENAME_EGlpNumInitVar (inf);
+ EGLPNUM_TYPENAME_EGlpNumZero (inf);
+
+ if (phase == DUAL_PHASEI)
+ {
+ if (ix == NULL)
+ for (i = 0; i < lp->nrows; i++)
+ {
+ compute_primalI_inf (lp, i, &inf);
+ update_p_scaleinf (p, h, i, inf, price);
+ }
+ else
+ for (i = 0; i < icnt; i++)
+ {
+ compute_primalI_inf (lp, ix[i], &inf);
+ update_p_scaleinf (p, h, ix[i], inf, price);
+ }
+ }
+ else if (phase == DUAL_PHASEII)
+ {
+ if (ix == NULL)
+ for (i = 0; i < lp->nrows; i++)
+ {
+ compute_primalII_inf (lp, i, &inf);
+ update_p_scaleinf (p, h, i, inf, price);
+ }
+ else
+ for (i = 0; i < icnt; i++)
+ {
+ compute_primalII_inf (lp, ix[i], &inf);
+ update_p_scaleinf (p, h, ix[i], inf, price);
+ }
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (inf);
+}
+
+void EGLPNUM_TYPENAME_ILLprice_dual (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_price_info * const pinf,
+ int const phase,
+ EGLPNUM_TYPENAME_price_res * const pr)
+{
+ int i;
+ EGLPNUM_TYPE p_max;
+ EGLPNUM_TYPE ubound;
+ EGLPNUM_TYPE*ftol = &(lp->tol->pfeas_tol);
+ EGLPNUM_TYPENAME_heap *const h = &(pinf->h);
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (p_max);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (ubound);
+ pr->lindex = -1;
+ EGLPNUM_TYPENAME_EGlpNumZero(p_max);
+
+#if USEHEAP > 0
+ EGLPNUM_TYPENAME_ILLprice_test_for_heap (lp, pinf, lp->nrows, pinf->p_scaleinf, DUAL_SIMPLEX,
+ 1);
+#endif
+
+ if (pinf->d_strategy == COMPLETE_PRICING)
+ {
+ if (h->hexist)
+ {
+ pr->lindex = EGLPNUM_TYPENAME_ILLheap_findmin (h);
+ if (pr->lindex != -1)
+ EGLPNUM_TYPENAME_ILLheap_delete (h, pr->lindex);
+ }
+ else
+ {
+ for (i = 0; i < lp->nrows; i++)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (p_max, pinf->p_scaleinf[i]))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (p_max, pinf->p_scaleinf[i]);
+ pr->lindex = i;
+ }
+ }
+ }
+ }
+ else if (pinf->d_strategy == MULTI_PART_PRICING)
+ {
+ for (i = 0; i < pinf->dmpinfo.bsize; i++)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (p_max, pinf->dmpinfo.infeas[i]))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (p_max, pinf->dmpinfo.infeas[i]);
+ pr->lindex = pinf->dmpinfo.bucket[i];
+ }
+ }
+ }
+
+ if (pr->lindex < 0)
+ pr->price_stat = PRICE_OPTIMAL;
+ else
+ {
+ pr->price_stat = NONOPTIMAL;
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (lp->uz[lp->baz[pr->lindex]], EGLPNUM_TYPENAME_INFTY))
+ {
+ if (phase == DUAL_PHASEI)
+ EGLPNUM_TYPENAME_EGlpNumZero(ubound);
+ else
+ EGLPNUM_TYPENAME_EGlpNumCopy(ubound,lp->uz[lp->baz[pr->lindex]]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsSumLess (*ftol, ubound, lp->xbz[pr->lindex]))
+ pr->lvstat = STAT_UPPER;
+ else
+ pr->lvstat = STAT_LOWER;
+ }
+ else
+ pr->lvstat = STAT_LOWER;
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (p_max);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ubound);
+}
+
+int EGLPNUM_TYPENAME_ILLprice_get_rownorms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_price_info * const pinf,
+ EGLPNUM_TYPE * const rnorms)
+{
+ int rval = 0;
+ int i;
+
+ if (pinf->dsinfo.norms == NULL)
+ {
+ rval = EGLPNUM_TYPENAME_ILLprice_build_dsteep_norms (lp, &(pinf->dsinfo));
+ CHECKRVALG(rval,CLEANUP);
+ }
+ for (i = 0; i < lp->nrows; i++)
+ EGLPNUM_TYPENAME_EGlpNumCopy (rnorms[i], pinf->dsinfo.norms[i]);
+
+CLEANUP:
+ if (rval)
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (pinf->dsinfo.norms);
+
+ return rval;
+}
+
+int EGLPNUM_TYPENAME_ILLprice_get_colnorms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_price_info * const pinf,
+ EGLPNUM_TYPE * const cnorms)
+{
+ int rval = 0;
+ int i, j;
+
+ if (pinf->psinfo.norms == NULL)
+ {
+ rval = EGLPNUM_TYPENAME_ILLprice_build_psteep_norms (lp, &(pinf->psinfo));
+ CHECKRVALG(rval,CLEANUP);
+ }
+ for (i = 0; i < lp->nrows; i++)
+ EGLPNUM_TYPENAME_EGlpNumZero (cnorms[lp->baz[i]]);
+ for (j = 0; j < lp->nnbasic; j++)
+ EGLPNUM_TYPENAME_EGlpNumCopy (cnorms[lp->nbaz[j]], pinf->psinfo.norms[j]);
+
+CLEANUP:
+ if (rval)
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (pinf->psinfo.norms);
+
+ return rval;
+}
+
+int EGLPNUM_TYPENAME_ILLprice_get_newnorms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ int const nelems,
+ EGLPNUM_TYPE * const norms,
+ int *const matcnt,
+ int *const matbeg,
+ int *const matind,
+ EGLPNUM_TYPE * const matval,
+ int const option)
+{
+ int i, j;
+ int rval = 0;
+ EGLPNUM_TYPENAME_svector a;
+ EGLPNUM_TYPENAME_svector y;
+
+ EGLPNUM_TYPENAME_ILLsvector_init (&y);
+ rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&y, lp->nrows);
+ CHECKRVALG(rval,CLEANUP);
+
+ for (j = 0; j < nelems; j++)
+ {
+ a.nzcnt = matcnt[j];
+ a.indx = &(matind[matbeg[j]]);
+ a.coef = &(matval[matbeg[j]]);
+
+ if (option == COLUMN_SOLVE)
+ EGLPNUM_TYPENAME_ILLbasis_column_solve (lp, &a, &y);
+ else
+ EGLPNUM_TYPENAME_ILLbasis_row_solve (lp, &a, &y);
+
+ EGLPNUM_TYPENAME_EGlpNumOne (norms[j]);
+ for (i = 0; i < y.nzcnt; i++)
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (norms[j], y.coef[i], y.coef[i]);
+ }
+
+CLEANUP:
+ EGLPNUM_TYPENAME_ILLsvector_free (&y);
+ EG_RETURN(rval);
+}
+
+int EGLPNUM_TYPENAME_ILLprice_get_new_rownorms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ int const newrows,
+ EGLPNUM_TYPE * const rnorms,
+ int *const rmatcnt,
+ int *const rmatbeg,
+ int *const rmatind,
+ EGLPNUM_TYPE * const rmatval)
+{
+ return EGLPNUM_TYPENAME_ILLprice_get_newnorms (lp, newrows, rnorms, rmatcnt, rmatbeg, rmatind,
+ rmatval, ROW_SOLVE);
+}
+
+int EGLPNUM_TYPENAME_ILLprice_get_new_colnorms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ int const newrows,
+ EGLPNUM_TYPE * const rnorms,
+ int *const matcnt,
+ int *const matbeg,
+ int *const matind,
+ EGLPNUM_TYPE * const matval)
+{
+ return EGLPNUM_TYPENAME_ILLprice_get_newnorms (lp, newrows, rnorms, matcnt, matbeg, matind,
+ matval, COLUMN_SOLVE);
+}
+
+int EGLPNUM_TYPENAME_ILLprice_load_rownorms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPE * const rnorms,
+ EGLPNUM_TYPENAME_price_info * const pinf)
+{
+ int i;
+ int rval = 0;
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (pinf->dsinfo.norms);
+ pinf->dsinfo.norms = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+
+ for (i = 0; i < lp->nrows; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (pinf->dsinfo.norms[i], rnorms[i]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (pinf->dsinfo.norms[i], EGLPNUM_TYPENAME_PARAM_MIN_DNORM))
+ EGLPNUM_TYPENAME_EGlpNumCopy (pinf->dsinfo.norms[i], EGLPNUM_TYPENAME_PARAM_MIN_DNORM);
+ }
+
+ EG_RETURN(rval);
+}
+
+int EGLPNUM_TYPENAME_ILLprice_load_colnorms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPE * const cnorms,
+ EGLPNUM_TYPENAME_price_info * const pinf)
+{
+ int j;
+ int rval = 0;
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (pinf->psinfo.norms);
+ pinf->psinfo.norms = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nnbasic);
+
+ for (j = 0; j < lp->nnbasic; j++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (pinf->psinfo.norms[j], cnorms[lp->nbaz[j]]);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (pinf->psinfo.norms[j], EGLPNUM_TYPENAME_oneLpNum))
+ EGLPNUM_TYPENAME_EGlpNumOne (pinf->psinfo.norms[j]);
+ }
+
+ EG_RETURN(rval);
+}
+
+#if PRICE_DEBUG > 0
+void EGLPNUM_TYPENAME_test_dsteep_norms (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * p)
+{
+ int i, errn = 0;
+ EGLPNUM_TYPE *pn = EGLPNUM_TYPENAME_EGlpNumAllocArray(lp->nrows);
+ EGLPNUM_TYPE err, diff;
+ EGLPNUM_TYPENAME_EGlpNumZero (err);
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (err);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (diff);
+
+ EGLPNUM_TYPENAME_ILLprice_get_dsteep_norms (lp, lp->yjz.nzcnt, lp->yjz.indx, pn);
+ for (i = 0; i < lp->yjz.nzcnt; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (diff, pn[i], p->dsinfo.norms[lp->yjz.indx[i]]);
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs(diff,diff);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_PFEAS_TOLER, diff))
+ {
+ errn++;
+ EGLPNUM_TYPENAME_EGlpNumAddTo (err, diff);
+ EGLPNUM_TYPENAME_EGlpNumCopy (p->dsinfo.norms[lp->yjz.indx[i]], pn[i]);
+ }
+ }
+ if (errn)
+ QSlog("%d: dnorm errn = %d, err = %.6f", lp->cnts->tot_iter, errn,
+ EGLPNUM_TYPENAME_EGlpNumToLf (err));
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (pn);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (diff);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (err);
+}
+#endif
diff --git a/qsopt_ex/price.h b/qsopt_ex/price.h
new file mode 100644
index 0000000..d477a19
--- /dev/null
+++ b/qsopt_ex/price.h
@@ -0,0 +1,222 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* $RCSfile: price_EGLPNUM_TYPENAME.h,v $ $Revision: 1.3 $ $Date: 2003/11/05 16:57:39 $" */
+#ifndef EGLPNUM_TYPENAME___PRICE_H
+#define EGLPNUM_TYPENAME___PRICE_H
+
+#include "dstruct_EGLPNUM_TYPENAME.h"
+#include "basicdefs.h"
+
+typedef struct EGLPNUM_TYPENAME_price_res
+{
+ int eindex;
+ int dir;
+ int lindex;
+ int lvstat;
+ int price_stat;
+ EGLPNUM_TYPE dinfeas;
+ EGLPNUM_TYPE pinfeas;
+}
+EGLPNUM_TYPENAME_price_res;
+
+int EGLPNUM_TYPENAME_ILLprice_test_for_heap (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_price_info * const pinf,
+ int const nkeys,
+ EGLPNUM_TYPE * keylist,
+ int const algo,
+ int const upd),
+ EGLPNUM_TYPENAME_ILLprice_build_heap (
+ EGLPNUM_TYPENAME_price_info * const pinf,
+ int const nkeys,
+ EGLPNUM_TYPE * keylist),
+ EGLPNUM_TYPENAME_ILLprice_build_pricing_info (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_price_info * const pinf,
+ int const phase),
+ EGLPNUM_TYPENAME_ILLprice_update_pricing_info (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_price_info * const pinf,
+ int const phase,
+ EGLPNUM_TYPENAME_svector * const wz,
+ int const eindex,
+ int const lindex,
+ EGLPNUM_TYPE y),
+ EGLPNUM_TYPENAME_ILLprice_get_price (
+ EGLPNUM_TYPENAME_price_info * const p,
+ int const phase),
+ EGLPNUM_TYPENAME_ILLprice_build_mpartial_info (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_price_info * const pinf,
+ int const pricetype),
+ EGLPNUM_TYPENAME_ILLprice_build_pdevex_norms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_p_devex_info * const pdinfo,
+ int const reinit),
+ EGLPNUM_TYPENAME_ILLprice_update_pdevex_norms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_p_devex_info * const pdinfo,
+ int const eindex,
+ EGLPNUM_TYPE yl),
+ EGLPNUM_TYPENAME_ILLprice_build_psteep_norms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_p_steep_info * const psinfo),
+ EGLPNUM_TYPENAME_ILLprice_build_ddevex_norms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_d_devex_info * const ddinfo,
+ int const reinit),
+ EGLPNUM_TYPENAME_ILLprice_update_ddevex_norms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_d_devex_info * const ddinfo,
+ int const eindex,
+ EGLPNUM_TYPE yl),
+ EGLPNUM_TYPENAME_ILLprice_build_dsteep_norms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_d_steep_info * const dsinfo),
+ EGLPNUM_TYPENAME_ILLprice_get_dsteep_norms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ int const count,
+ int *constrowind,
+ EGLPNUM_TYPE * const norms),
+ EGLPNUM_TYPENAME_ILLprice_get_rownorms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_price_info * const pinf,
+ EGLPNUM_TYPE * const rnorms),
+ EGLPNUM_TYPENAME_ILLprice_get_colnorms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_price_info * const pinf,
+ EGLPNUM_TYPE * const cnorms),
+ EGLPNUM_TYPENAME_ILLprice_get_newnorms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ int const nelems,
+ EGLPNUM_TYPE * const norms,
+ int *const matcnt,
+ int *const matbeg,
+ int *const matind,
+ EGLPNUM_TYPE * const matval,
+ int const option),
+ EGLPNUM_TYPENAME_ILLprice_get_new_rownorms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ int const newrows,
+ EGLPNUM_TYPE * const rnorms,
+ int *const rmatcnt,
+ int *const rmatbeg,
+ int *const rmatind,
+ EGLPNUM_TYPE * const rmatval),
+ EGLPNUM_TYPENAME_ILLprice_get_new_colnorms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ int const newrows,
+ EGLPNUM_TYPE * const rnorms,
+ int *const matcnt,
+ int *const matbeg,
+ int *const matind,
+ EGLPNUM_TYPE * const matval),
+ EGLPNUM_TYPENAME_ILLprice_load_rownorms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPE * const rnorms,
+ EGLPNUM_TYPENAME_price_info * const pinf),
+ EGLPNUM_TYPENAME_ILLprice_load_colnorms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPE * const cnorms,
+ EGLPNUM_TYPENAME_price_info * const pinf);
+
+
+void EGLPNUM_TYPENAME_ILLprice_free_heap (
+ EGLPNUM_TYPENAME_price_info * const pinf),
+ EGLPNUM_TYPENAME_ILLprice_init_pricing_info (
+ EGLPNUM_TYPENAME_price_info * const pinf),
+ EGLPNUM_TYPENAME_ILLprice_free_pricing_info (
+ EGLPNUM_TYPENAME_price_info * const pinf),
+ EGLPNUM_TYPENAME_ILLprice_free_mpartial_info (
+ EGLPNUM_TYPENAME_mpart_info * p),
+ EGLPNUM_TYPENAME_ILLprice_init_mpartial_price (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_price_info * const pinf,
+ int const phase,
+ int const pricetype),
+ EGLPNUM_TYPENAME_ILLprice_update_mpartial_price (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_price_info * const pinf,
+ int const phase,
+ int const pricetype),
+ EGLPNUM_TYPENAME_ILLprice_delete_onempart_price (
+ /*EGLPNUM_TYPENAME_lpinfo * const lp,*/
+ EGLPNUM_TYPENAME_price_info * const pinf,
+ int const indx,
+ int const pricetype),
+ EGLPNUM_TYPENAME_ILLprice_mpartial_group (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_mpart_info * const p,
+ int const phase,
+ int const g,
+ int const pricetype),
+ EGLPNUM_TYPENAME_ILLprice_column (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ int const ix,
+ int const phase,
+ EGLPNUM_TYPENAME_price_res * const pr),
+ EGLPNUM_TYPENAME_ILLprice_row (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ int const ix,
+ int const phase,
+ EGLPNUM_TYPENAME_price_res * const pr),
+ EGLPNUM_TYPENAME_ILLprice_update_psteep_norms (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_p_steep_info * psinfo,
+ EGLPNUM_TYPENAME_svector * wz,
+ int eindex,
+ EGLPNUM_TYPE yl),
+ EGLPNUM_TYPENAME_ILLprice_update_dsteep_norms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_d_steep_info * const dsinfo,
+ EGLPNUM_TYPENAME_svector * const wz,
+ int const lindex,
+ EGLPNUM_TYPE yl),
+ EGLPNUM_TYPENAME_ILLprice_compute_dual_inf (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_price_info * const p,
+ int *const ix,
+ int const icnt,
+ int const phase),
+ EGLPNUM_TYPENAME_ILLprice_primal (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_price_info * const pinf,
+ EGLPNUM_TYPENAME_price_res * const pr,
+ int const phase),
+ EGLPNUM_TYPENAME_ILLprice_compute_primal_inf (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_price_info * const p,
+ int *const ix,
+ int const icnt,
+ int const phase),
+ EGLPNUM_TYPENAME_ILLprice_dual (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_price_info * const pinf,
+ int const phase,
+ EGLPNUM_TYPENAME_price_res * const pr);
+
+void EGLPNUM_TYPENAME_test_dsteep_norms (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ EGLPNUM_TYPENAME_price_info * const p);
+
+#endif /* EGLPNUM_TYPENAME___PRICE_H */
diff --git a/qsopt_ex/priority.c b/qsopt_ex/priority.c
new file mode 100644
index 0000000..93b3647
--- /dev/null
+++ b/qsopt_ex/priority.c
@@ -0,0 +1,259 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCSINFO $Id: priority.c,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+/****************************************************************************/
+/* */
+/* This file is part of CONCORDE */
+/* */
+/* (c) Copyright 1995--1999 by David Applegate, Robert Bixby, */
+/* Vasek Chvatal, and William Cook */
+/* */
+/* Permission is granted for academic research use. For other uses, */
+/* contact the authors for licensing options. */
+/* */
+/* Use at your own risk. We make no guarantees about the */
+/* correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* PRIORITY QUEUE ROUTINES */
+/* */
+/* */
+/* TSP CODE */
+/* Written by: Applegate, Bixby, Chvatal, and Cook */
+/* Date: March 3, 1997 */
+/* March 13, 2002 - Cook Modified for QS) */
+/* Reference: R.E. Tarjan, Data Structures and Network Algorithms */
+/* */
+/* EXPORTED FUNCTIONS: */
+/* */
+/* int EGLPNUM_TYPENAME_ILLutil_priority_init (EGLPNUM_TYPENAME_ILLpriority *pri, int k) */
+/* -h should point to a EGLPNUM_TYPENAME_ILLpriority struct. */
+/* -k an initial allocation for the priority queue. */
+/* */
+/* void EGLPNUM_TYPENAME_ILLutil_priority_free (EGLPNUM_TYPENAME_ILLpriority *pri) */
+/* -frees the spaces allocated for the EGLPNUM_TYPENAME_ILLpriority queue. */
+/* */
+/* void EGLPNUM_TYPENAME_ILLutil_priority_findmin (EGLPNUM_TYPENAME_ILLpriority *pri, double *keyval */
+/* void **en) */
+/* -en the entry with least key value (NULL if no entries in EGLPNUM_TYPENAME_heap). */
+/* -if (keyval != NULL), *keyval will be the minimum key value. */
+/* */
+/* int EGLPNUM_TYPENAME_ILLutil_priority_insert (EGLPNUM_TYPENAME_ILLpriority *pri, void *data, */
+/* double keyval, int *handle) */
+/* -adds (data, keyval) to h. */
+/* -handle returns a handle (>= 0) to use when deleting or changing the */
+/* entry */
+/* */
+/* void EGLPNUM_TYPENAME_ILLutil_priority_delete (EGLPNUM_TYPENAME_ILLpriority *pri, int handle) */
+/* -deletes an entry from the queue. handle is the value returned by */
+/* EGLPNUM_TYPENAME_ILLutil_priority_insert. */
+/* */
+/* void EGLPNUM_TYPENAME_ILLutil_priority_deletemin (EGLPNUM_TYPENAME_ILLpriority *pri, double *keyval, */
+/* void **en) */
+/* -like EGLPNUM_TYPENAME_ILLutil_priority_findmin, but also deletes the entry. */
+/* */
+/* void EGLPNUM_TYPENAME_ILLutil_priority_changekey (EGLPNUM_TYPENAME_ILLpriority *pri, int handle, */
+/* double newkey) */
+/* -changes the key of an entry in the queue. handle is the value */
+/* returned by EGLPNUM_TYPENAME_ILLutil_priority_insert. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* NOTES: */
+/* These priority queue routines use the EGLPNUM_TYPENAME_ILLdheap routines to maintain */
+/* the priority queue. */
+/* */
+/****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "eg_lpnum.h"
+
+#include "priority_EGLPNUM_TYPENAME.h"
+#include "allocrus.h"
+#include "except.h"
+
+
+int EGLPNUM_TYPENAME_ILLutil_priority_init (
+ EGLPNUM_TYPENAME_ILLpriority * pri,
+ int k)
+{
+ int i;
+ int list;
+ int rval = 0;
+
+ pri->space = k;
+ ILL_SAFE_MALLOC (pri->pri_info, k, union EGLPNUM_TYPENAME_ILLpri_data);
+
+ rval = EGLPNUM_TYPENAME_ILLutil_dheap_init (&pri->EGLPNUM_TYPENAME_heap, k);
+ ILL_CLEANUP_IF (rval);
+
+ list = -1;
+ for (i = k - 1; i >= 0; i--)
+ {
+ pri->pri_info[i].next = list;
+ list = i;
+ }
+ pri->freelist = list;
+
+CLEANUP:
+
+ if (rval)
+ {
+ ILL_IFFREE (pri->pri_info, union EGLPNUM_TYPENAME_ILLpri_data);
+ }
+ return rval;
+}
+
+void EGLPNUM_TYPENAME_ILLutil_priority_free (
+ EGLPNUM_TYPENAME_ILLpriority * pri)
+{
+ EGLPNUM_TYPENAME_ILLutil_dheap_free (&pri->EGLPNUM_TYPENAME_heap);
+ ILL_IFFREE (pri->pri_info, union EGLPNUM_TYPENAME_ILLpri_data);
+
+ pri->space = 0;
+}
+
+void EGLPNUM_TYPENAME_ILLutil_priority_findmin (
+ EGLPNUM_TYPENAME_ILLpriority * pri,
+ EGLPNUM_TYPE * keyval,
+ void **en)
+{
+ int handle;
+
+ EGLPNUM_TYPENAME_ILLutil_dheap_findmin (&pri->EGLPNUM_TYPENAME_heap, &handle);
+
+ if (handle < 0)
+ {
+ *en = (void *) NULL;
+ }
+ else
+ {
+ if (keyval)
+ EGLPNUM_TYPENAME_EGlpNumCopy (*keyval, pri->EGLPNUM_TYPENAME_heap.key[handle]);
+ *en = pri->pri_info[handle].data;
+ }
+}
+
+int EGLPNUM_TYPENAME_ILLutil_priority_insert (
+ EGLPNUM_TYPENAME_ILLpriority * pri,
+ void *data,
+ EGLPNUM_TYPE * keyval,
+ int *handle)
+{
+ int newsize;
+ int i;
+ int list;
+ int rval = 0;
+
+ if (pri->freelist == -1)
+ {
+ /* Change from 1.3 * pri->space to avoid a warning */
+ newsize = pri->space + (pri->space / 3);
+ if (newsize < pri->space + 1000)
+ newsize = pri->space + 1000;
+ rval = EGLPNUM_TYPENAME_ILLutil_dheap_resize (&pri->EGLPNUM_TYPENAME_heap, newsize);
+ ILL_CLEANUP_IF (rval);
+
+ pri->pri_info =
+ EGrealloc (pri->pri_info, sizeof (union EGLPNUM_TYPENAME_ILLpri_data) * newsize);
+ //rval = ILLutil_reallocrus_count ((void **) &pri->pri_info, newsize,
+ // sizeof (union EGLPNUM_TYPENAME_ILLpri_data));
+ //ILL_CLEANUP_IF (rval);
+
+ list = -1;
+ for (i = newsize - 1; i >= pri->space; i--)
+ {
+ pri->pri_info[i].next = list;
+ list = i;
+ }
+ pri->space = newsize;
+ pri->freelist = list;
+ }
+
+ i = pri->freelist;
+ pri->freelist = pri->pri_info[i].next;
+ pri->pri_info[i].data = data;
+ EGLPNUM_TYPENAME_EGlpNumCopy (pri->EGLPNUM_TYPENAME_heap.key[i], *keyval);
+ rval = EGLPNUM_TYPENAME_ILLutil_dheap_insert (&pri->EGLPNUM_TYPENAME_heap, i);
+ ILL_CLEANUP_IF (rval);
+
+ if (handle)
+ *handle = i;
+
+CLEANUP:
+
+ return rval;
+}
+
+void EGLPNUM_TYPENAME_ILLutil_priority_delete (
+ EGLPNUM_TYPENAME_ILLpriority * pri,
+ int handle)
+{
+ EGLPNUM_TYPENAME_ILLutil_dheap_delete (&pri->EGLPNUM_TYPENAME_heap, handle);
+ pri->pri_info[handle].next = pri->freelist;
+ pri->freelist = handle;
+}
+
+void EGLPNUM_TYPENAME_ILLutil_priority_deletemin (
+ EGLPNUM_TYPENAME_ILLpriority * pri,
+ EGLPNUM_TYPE * keyval,
+ void **en)
+{
+ int handle;
+ void *data;
+
+ EGLPNUM_TYPENAME_ILLutil_dheap_deletemin (&pri->EGLPNUM_TYPENAME_heap, &handle);
+
+ if (handle < 0)
+ {
+ *en = (void *) NULL;
+ }
+ else
+ {
+ if (keyval)
+ EGLPNUM_TYPENAME_EGlpNumCopy (*keyval, pri->EGLPNUM_TYPENAME_heap.key[handle]);
+ data = pri->pri_info[handle].data;
+ pri->pri_info[handle].next = pri->freelist;
+ pri->freelist = handle;
+ *en = data;
+ }
+}
+
+void EGLPNUM_TYPENAME_ILLutil_priority_changekey (
+ EGLPNUM_TYPENAME_ILLpriority * pri,
+ int handle,
+ EGLPNUM_TYPE * newkey)
+{
+ EGLPNUM_TYPENAME_ILLutil_dheap_changekey (&pri->EGLPNUM_TYPENAME_heap, handle, newkey);
+}
diff --git a/qsopt_ex/priority.h b/qsopt_ex/priority.h
new file mode 100644
index 0000000..6bf6d5c
--- /dev/null
+++ b/qsopt_ex/priority.h
@@ -0,0 +1,75 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+#ifndef EGLPNUM_TYPENAME___PRIORITY_H__
+#define EGLPNUM_TYPENAME___PRIORITY_H__
+#include "dheaps_i_EGLPNUM_TYPENAME.h"
+/****************************************************************************/
+/* */
+/* priority.c */
+/* */
+/****************************************************************************/
+
+typedef struct EGLPNUM_TYPENAME_ILLpriority
+{
+ EGLPNUM_TYPENAME_ILLdheap EGLPNUM_TYPENAME_heap;
+ union EGLPNUM_TYPENAME_ILLpri_data
+ {
+ void *data;
+ int next;
+ }
+ *pri_info;
+ int space;
+ int freelist;
+}
+EGLPNUM_TYPENAME_ILLpriority;
+
+void EGLPNUM_TYPENAME_ILLutil_priority_free (
+ EGLPNUM_TYPENAME_ILLpriority * pri),
+ EGLPNUM_TYPENAME_ILLutil_priority_delete (
+ EGLPNUM_TYPENAME_ILLpriority * pri,
+ int handle),
+ EGLPNUM_TYPENAME_ILLutil_priority_changekey (
+ EGLPNUM_TYPENAME_ILLpriority * pri,
+ int handle,
+ EGLPNUM_TYPE * newkey),
+ EGLPNUM_TYPENAME_ILLutil_priority_findmin (
+ EGLPNUM_TYPENAME_ILLpriority * pri,
+ EGLPNUM_TYPE * keyval,
+ void **en),
+ EGLPNUM_TYPENAME_ILLutil_priority_deletemin (
+ EGLPNUM_TYPENAME_ILLpriority * pri,
+ EGLPNUM_TYPE * keyval,
+ void **en);
+
+int EGLPNUM_TYPENAME_ILLutil_priority_init (
+ EGLPNUM_TYPENAME_ILLpriority * pri,
+ int k),
+ EGLPNUM_TYPENAME_ILLutil_priority_insert (
+ EGLPNUM_TYPENAME_ILLpriority * pri,
+ void *data,
+ EGLPNUM_TYPE * keyval,
+ int *handle);
+
+
+
+#endif
diff --git a/qsopt_ex/qs_config.h b/qsopt_ex/qs_config.h
new file mode 100644
index 0000000..52afce5
--- /dev/null
+++ b/qsopt_ex/qs_config.h
@@ -0,0 +1,70 @@
+/* Taken from EGlib 10-09-26 */
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ *
+ * 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
+ * */
+/* ========================================================================= */
+/** Main Configuration for the library, as debug levels and so on
+ *
+ * @par History:
+ * - 2010-09-26
+ * - Addapted for QSopt_ex
+ * - 2010-08-13
+ * - Add suport for autoconf and configure for header and feature
+ * selection
+ * - 2006-01-27
+ * - Handle some problems with stdint.h in SUN
+ * - 2005-08-17
+ * - Set memory aligment to 8 bits
+ * - 2003-06-02
+ * - First Implementation
+ * @version 1.1.1
+ * */
+/* ========================================================================= */
+#ifndef __QS_CONFIG_H__
+#define __QS_CONFIG_H__
+
+#if ! defined(_XOPEN_SOURCE) || _XOPEN_SOURCE < 600
+# define _XOPEN_SOURCE 600
+#endif
+
+#define EG_NEWLINE "\n"
+
+/* ========================================================================= */
+/** @brief see if we have both pthread library and header file available, if
+ * so, define HAVE_EG_THREAD */
+#if defined HAVE_PTHREAD_H && HAVE_PTHREAD_H && defined HAVE_LIBPTHREAD && HAVE_LIBPTHREAD
+#define HAVE_EG_THREAD 1
+#else
+#define HAVE_EG_THREAD 0
+#endif
+
+/* ========================================================================= */
+/** @brief assert Debug options definitions, by defoult set on */
+#ifndef DEBUG
+#warning you should define DEBUG, assuming it to be 1
+#define DEBUG 1
+#endif
+
+/* ========================================================================= */
+/** @brief assert Verbose options definition, by default set on */
+#ifndef VERBOSE_LEVEL
+#warning you should define VERBOSE_LEVEL, assuming it to be 1
+#define VERBOSE_LEVEL 1
+#endif
+#endif
diff --git a/qsopt_ex/qsopt.c b/qsopt_ex/qsopt.c
new file mode 100644
index 0000000..05c53dd
--- /dev/null
+++ b/qsopt_ex/qsopt.c
@@ -0,0 +1,3933 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: qsopt.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+static int TRACE = 0;
+
+/****************************************************************************/
+/* */
+/* User-level Functions */
+/* */
+/* EXPORTED FUNCTIONS */
+/* */
+/* int EGLPNUM_TYPENAME_QSopt_primal (EGLPNUM_TYPENAME_QSdata *p, int *status) */
+/* int EGLPNUM_TYPENAME_QSopt_dual (EGLPNUM_TYPENAME_QSdata *p, int *status) */
+/* EGLPNUM_TYPENAME_QSdata *EGLPNUM_TYPENAME_QScreate_prob (const char *name, int objsense) */
+/* EGLPNUM_TYPENAME_QSdata *EGLPNUM_TYPENAME_QSread_prob (const char *filename, const char *filetype) */
+/* EGLPNUM_TYPENAME_QSdata *EGLPNUM_TYPENAME_QSload_prob (const char *probname, int ncols, int nrows, */
+/* int *cmatcnt, int *cmatbeg, int *cmatind, double *cmatval, */
+/* int objsense, double *obj, double *rhs, char *sense, */
+/* double *lower, double *upper, const char **colnames, */
+/* const char **rownames) */
+/* EGLPNUM_TYPENAME_QSdata *EGLPNUM_TYPENAME_QScopy_prob (EGLPNUM_TYPENAME_QSdata *p, const char *newname) */
+/* int EGLPNUM_TYPENAME_QSchange_objsense (EGLPNUM_TYPENAME_QSdata *p, int newsense) */
+/* int EGLPNUM_TYPENAME_QSget_objsense (EGLPNUM_TYPENAME_QSdata *p, int *objsense) */
+/* int EGLPNUM_TYPENAME_QSnew_col (EGLPNUM_TYPENAME_QSdata *p, double obj, double lower, double upper, */
+/* const char *name) */
+/* int EGLPNUM_TYPENAME_QSadd_cols (EGLPNUM_TYPENAME_QSdata *p, int num, int *cmatcnt, int *cmatbeg, */
+/* int *cmatind, double *cmatval, double *obj, double *lower, */
+/* double *upper, const char **names) */
+/* int EGLPNUM_TYPENAME_QSadd_col (EGLPNUM_TYPENAME_QSdata *p, int cnt, int *cmatind, double *cmatval, */
+/* double obj, double lower, double upper, const char *name) */
+/* int EGLPNUM_TYPENAME_QSnew_row (EGLPNUM_TYPENAME_QSdata *p, double rhs, const char sense, char *name) */
+/* int EGLPNUM_TYPENAME_QSadd_rows (EGLPNUM_TYPENAME_QSdata *p, int num, int *rmatcnt, int *rmatbeg, */
+/* int *rmatind, double *rmatval, double *rhs, char *sense, */
+/* char **names) */
+/* int EGLPNUM_TYPENAME_QSadd_row (EGLPNUM_TYPENAME_QSdata *p, int cnt, int *rmatind, double *rmatval, */
+/* double rhs, char sense, const char *name) */
+/* int EGLPNUM_TYPENAME_QSdelete_rows (EGLPNUM_TYPENAME_QSdata *p, int num, int *dellist) */
+/* int EGLPNUM_TYPENAME_QSdelete_row (EGLPNUM_TYPENAME_QSdata *p, int rowindex) */
+/* int EGLPNUM_TYPENAME_QSdelete_setrows (EGLPNUM_TYPENAME_QSdata *p, int *flags) */
+/* int EGLPNUM_TYPENAME_QSdelete_cols (EGLPNUM_TYPENAME_QSdata *p, int num, int *dellist) */
+/* int EGLPNUM_TYPENAME_QSdelete_col (EGLPNUM_TYPENAME_QSdata *p, int colindex) */
+/* int EGLPNUM_TYPENAME_QSdelete_setcols (EGLPNUM_TYPENAME_QSdata *p, int *flags) */
+/* int EGLPNUM_TYPENAME_QSdelete_named_column (EGLPNUM_TYPENAME_QSdata *p, const char *colname) */
+/* int EGLPNUM_TYPENAME_QSdelete_named_columns_list (EGLPNUM_TYPENAME_QSdata *p, int num, */
+/* const char **colnames) */
+/* int EGLPNUM_TYPENAME_QSdelete_named_row (EGLPNUM_TYPENAME_QSdata *p, const char *rowname) */
+/* int EGLPNUM_TYPENAME_QSdelete_named_rows_list (EGLPNUM_TYPENAME_QSdata *p, int num, */
+/* const char **rownames) */
+/* int EGLPNUM_TYPENAME_QSchange_senses (EGLPNUM_TYPENAME_QSdata *p, int num, int *rowlist, char *sense) */
+/* int EGLPNUM_TYPENAME_QSchange_sense (EGLPNUM_TYPENAME_QSdata *p, int rowindex, char sense) */
+/* int EGLPNUM_TYPENAME_QSchange_coef (EGLPNUM_TYPENAME_QSdata *p, int rowindex, int colindex, */
+/* double coef) */
+/* int EGLPNUM_TYPENAME_QSchange_objcoef (EGLPNUM_TYPENAME_QSdata *p, int indx, double coef) */
+/* int EGLPNUM_TYPENAME_QSchange_rhscoef (EGLPNUM_TYPENAME_QSdata *p, int indx, double coef) */
+/* int EGLPNUM_TYPENAME_QSchange_bounds (EGLPNUM_TYPENAME_QSdata *p, int num, int *collist, char *lu, */
+/* double *bounds) */
+/* int EGLPNUM_TYPENAME_QSchange_bound (EGLPNUM_TYPENAME_QSdata *p, int indx, char lu, double bound) */
+/* int EGLPNUM_TYPENAME_QSwrite_basis (EGLPNUM_TYPENAME_QSdata *p, QSbasis *B, const char *filename) */
+/* QSbasis *EGLPNUM_TYPENAME_QSget_basis (EGLPNUM_TYPENAME_QSdata *p) */
+/* QSbasis *EGLPNUM_TYPENAME_QSread_basis (EGLPNUM_TYPENAME_QSdata *p, const char *filename) */
+/* int EGLPNUM_TYPENAME_QSload_basis (EGLPNUM_TYPENAME_QSdata *p, QSbasis *B) */
+/* int EGLPNUM_TYPENAME_QSread_and_load_basis (EGLPNUM_TYPENAME_QSdata *p, const char *filename) */
+/* int EGLPNUM_TYPENAME_QSload_basis_array (EGLPNUM_TYPENAME_QSdata *p, char *cstat, char *rstat) */
+/* int EGLPNUM_TYPENAME_QSload_basis_and_row_norms_array (EGLPNUM_TYPENAME_QSdata *p, char *cstat, */
+/* char *rstat, double *rownorms) */
+/* int EGLPNUM_TYPENAME_QSget_basis_array (EGLPNUM_TYPENAME_QSdata *p, char *cstat, char *rstat) */
+/* int EGLPNUM_TYPENAME_QSget_basis_and_row_norms_array (EGLPNUM_TYPENAME_QSdata *p, char *cstat, */
+/* char *rstat, double *rownorms) */
+/* int EGLPNUM_TYPENAME_QSget_binv_row (EGLPNUM_TYPENAME_QSdata *p, int indx, double *binvrow) */
+/* int EGLPNUM_TYPENAME_QSget_tableau_row (EGLPNUM_TYPENAME_QSdata *p, int indx, double *tableaurow) */
+/* int EGLPNUM_TYPENAME_QSget_basis_order (EGLPNUM_TYPENAME_QSdata *p, int *basorder) */
+/* int EGLPNUM_TYPENAME_QSget_status (EGLPNUM_TYPENAME_QSdata *p, int *status) */
+/* int EGLPNUM_TYPENAME_QSget_solution (EGLPNUM_TYPENAME_QSdata *p, double *value, double *x, */
+/* double *pi, double *slack, double *rc), */
+/* int EGLPNUM_TYPENAME_QSget_objval (EGLPNUM_TYPENAME_QSdata *p, double *value) */
+/* int EGLPNUM_TYPENAME_QSget_x_array (EGLPNUM_TYPENAME_QSdata *p, double *x) */
+/* int EGLPNUM_TYPENAME_QSget_rc_array (EGLPNUM_TYPENAME_QSdata *p, double *rc) */
+/* int EGLPNUM_TYPENAME_QSget_pi_array (EGLPNUM_TYPENAME_QSdata *p, double *pi) */
+/* int EGLPNUM_TYPENAME_QSget_slack_array (EGLPNUM_TYPENAME_QSdata *p, double *slack) */
+/* int EGLPNUM_TYPENAME_QSget_infeas_array (EGLPNUM_TYPENAME_QSdata *p, double *pi) */
+/* int EGLPNUM_TYPENAME_QSget_named_x (EGLPNUM_TYPENAME_QSdata *p, const char *colname, double *val) */
+/* int EGLPNUM_TYPENAME_QSget_named_rc (EGLPNUM_TYPENAME_QSdata *p, const char *colname, double *val) */
+/* int EGLPNUM_TYPENAME_QSget_named_pi (EGLPNUM_TYPENAME_QSdata *p, const char *rowname, double *val) */
+/* int EGLPNUM_TYPENAME_QSget_named_slack (EGLPNUM_TYPENAME_QSdata *p, const char *rowname, double *val) */
+/* int EGLPNUM_TYPENAME_QSget_colcount (EGLPNUM_TYPENAME_QSdata *p) */
+/* int EGLPNUM_TYPENAME_QSget_rowcount (EGLPNUM_TYPENAME_QSdata *p) */
+/* int EGLPNUM_TYPENAME_QSget_nzcount (EGLPNUM_TYPENAME_QSdata *p) */
+/* int EGLPNUM_TYPENAME_QSget_obj (EGLPNUM_TYPENAME_QSdata *p, double *obj), */
+/* int EGLPNUM_TYPENAME_QSget_rhs (EGLPNUM_TYPENAME_QSdata *p, double *rhs) */
+/* char* EGLPNUM_TYPENAME_QSget_probname (EGLPNUM_TYPENAME_QSdata *p) */
+/* char* EGLPNUM_TYPENAME_QSget_objname (EGLPNUM_TYPENAME_QSdata *p) */
+/* int EGLPNUM_TYPENAME_QSget_columns (EGLPNUM_TYPENAME_QSdata *p, int **colcnt, int **colbeg, */
+/* int **colind, double **colval, double **obj, double **lower, */
+/* double **upper, char ***names) */
+/* int EGLPNUM_TYPENAME_QSget_columns_list (EGLPNUM_TYPENAME_QSdata *p, int num, int *collist, */
+/* int **colcnt, int **colbeg, int **colind, double **colval, */
+/* double **obj, double **lower, double **upper, char ***names) */
+/* int EGLPNUM_TYPENAME_QSget_rows (EGLPNUM_TYPENAME_QSdata *p, int **rowcnt, int **rowbeg, int **rowind, */
+/* double **rowval, double **rhs, char **sense, char ***names) */
+/* int EGLPNUM_TYPENAME_QSget_rows_list (EGLPNUM_TYPENAME_QSdata *p, int num, int *rowlist, int **rowcnt, */
+/* int **rowbeg, int **rowind, double **rowval, double **rhs, */
+/* char **sense, char ***names) */
+/* int EGLPNUM_TYPENAME_QSget_column_index (EGLPNUM_TYPENAME_QSdata *p, const char *name, int *colindex) */
+/* int EGLPNUM_TYPENAME_QSget_row_index (EGLPNUM_TYPENAME_QSdata *p, const char *name, int *rowindex) */
+/* int EGLPNUM_TYPENAME_QSget_rownames (EGLPNUM_TYPENAME_QSdata *p, char **rownames) */
+/* int EGLPNUM_TYPENAME_QSget_colnames (EGLPNUM_TYPENAME_QSdata *p, char **colnames) */
+/* int EGLPNUM_TYPENAME_QSget_bound (EGLPNUM_TYPENAME_QSdata *p, int colindex, char lu, double *bound) */
+/* int EGLPNUM_TYPENAME_QSget_bounds (EGLPNUM_TYPENAME_QSdata *p, double *lower, double *upper) */
+/* int EGLPNUM_TYPENAME_QSget_intcount (EGLPNUM_TYPENAME_QSdata *p, int *count) */
+/* int EGLPNUM_TYPENAME_QSget_intflags (EGLPNUM_TYPENAME_QSdata *p, int *intflags) */
+/* int EGLPNUM_TYPENAME_QScompute_row_norms (EGLPNUM_TYPENAME_QSdata *p) */
+/* void EGLPNUM_TYPENAME_QSfree_prob (EGLPNUM_TYPENAME_QSdata *p) */
+/* void EGLPNUM_TYPENAME_QSfree_basis (QSbasis *B) */
+/* int EGLPNUM_TYPENAME_QSwrite_prob (EGLPNUM_TYPENAME_QSdata *p, const char *filename, */
+/* const char *filetype) */
+/* int EGLPNUM_TYPENAME_QSwrite_prob_file (EGLPNUM_TYPENAME_QSdata *p, FILE *file, const char *filetype) */
+/* int EGLPNUM_TYPENAME_QSset_param (EGLPNUM_TYPENAME_QSdata *p, int whichparam, int newvalue) */
+/* int QSset_param_double (EGLPNUM_TYPENAME_QSdata *p, int whichparam, double newvalue) */
+/* int EGLPNUM_TYPENAME_QSget_param (EGLPNUM_TYPENAME_QSdata *p, int whichparam, int *value) */
+/* int QSget_param_double (EGLPNUM_TYPENAME_QSdata *p, int whichparam, double *value) */
+/* int EGLPNUM_TYPENAME_QStest_row_norms (EGLPNUM_TYPENAME_QSdata *p) */
+/* int EGLPNUM_TYPENAME_QSopt_strongbranch (EGLPNUM_TYPENAME_QSdata *p, int ncand, int *candidatelist, */
+/* double *xlist, double *down_vals, double *up_vals, */
+/* int iterations, double objbound) */
+/* int EGLPNUM_TYPENAME_QSopt_pivotin_row (EGLPNUM_TYPENAME_QSdata *p, int rcnt, int *rlist) */
+/* int EGLPNUM_TYPENAME_QSopt_pivotin_col (EGLPNUM_TYPENAME_QSdata *p, int ccnt, int *clist) */
+/* void EGLPNUM_TYPENAME_QSfree (void *ptr) */
+/* void EGLPNUM_TYPENAME_QSstart (void) */
+/* void EGLPNUM_TYPENAME_QSend (void) */
+/* char *EGLPNUM_TYPENAME_QSversion (void)) */
+/* */
+/* NEW FUNCTIONS - Add to Docs */
+/* */
+/* char *EGLPNUM_TYPENAME_QSversion (void)) */
+/* int EGLPNUM_TYPENAME_QSget_objsense (EGLPNUM_TYPENAME_QSdata *p, int *objsense) */
+/* */
+/****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "qsopt_EGLPNUM_TYPENAME.h"
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "eg_lpnum.h"
+#include "eg_io.h"
+#include "except.h"
+#include "util.h"
+
+#include "lpdata_EGLPNUM_TYPENAME.h"
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+#include "simplex_EGLPNUM_TYPENAME.h"
+#include "price_EGLPNUM_TYPENAME.h"
+#include "qstruct_EGLPNUM_TYPENAME.h"
+#include "lib_EGLPNUM_TYPENAME.h"
+#include "mps_EGLPNUM_TYPENAME.h"
+#include "lp_EGLPNUM_TYPENAME.h"
+
+
+void EGLPNUM_TYPENAME_QSset_precision (
+ const unsigned prec)
+{
+ EGlpNumSetPrecision (prec);
+ EGLPNUM_TYPENAME_ILLchange_precision ();
+ /* change the numbers */
+}
+
+static void init_basis (
+ QSbasis * B),
+ free_cache (
+ EGLPNUM_TYPENAME_QSdata * p);
+
+static int opt_work ( EGLPNUM_TYPENAME_QSdata * p, int *status, int primal_or_dual),
+ qsbasis_to_illbasis ( QSbasis * qB, EGLPNUM_TYPENAME_ILLlp_basis * B),
+ illbasis_to_qsbasis ( EGLPNUM_TYPENAME_ILLlp_basis * B, QSbasis * qB),
+ grab_basis ( EGLPNUM_TYPENAME_QSdata * p),
+ check_qsdata_pointer ( EGLPNUM_TYPENAME_QSdata * p);
+
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSopt_primal (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int *status)
+{
+ int rval = 0;
+
+ if (status)
+ *status = QS_LP_UNSOLVED;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ /* If both the basis and the cache exist, then skip the optimization */
+
+ if (!p->basis || !p->cache)
+ {
+ rval = opt_work (p, status, 0);
+ CHECKRVALG (rval, CLEANUP);
+ }
+ else
+ {
+ if (status)
+ *status = p->cache->status;
+ }
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSopt_dual (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int *status)
+{
+ int rval = 0;
+
+ if (status)
+ *status = QS_LP_UNSOLVED;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (!p->basis || !p->cache || !p->factorok)
+ {
+ rval = opt_work (p, status, 1);
+ CHECKRVALG (rval, CLEANUP);
+ }
+ else
+ {
+ if (status)
+ *status = p->cache->status;
+ }
+
+CLEANUP:
+
+ if (rval == QS_LP_CHANGE_PREC)
+ {
+ MESSAGE (__QS_SB_VERB, "Changing precision");
+ return rval;
+ }
+ EG_RETURN (rval);
+}
+
+static int opt_work (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int *status,
+ int primal_or_dual)
+{
+ int rval = 0;
+ int rstatus = QS_LP_UNSOLVED;
+ EGLPNUM_TYPENAME_QSdata *p2 = 0;
+
+ if (p->basis)
+ {
+ if (p->basis->nstruct != p->qslp->nstruct ||
+ p->basis->nrows != p->qslp->nrows)
+ {
+ QSlog("Size of basis does not match LP");
+ rval = 1;
+ goto CLEANUP;
+ }
+ }
+
+ if (!p->basis && p->lp->basisid == -1 && p->simplex_scaling == 1)
+ {
+ /* Try scaling by copying the LP and solving */
+
+ EGLPNUM_TYPENAME_ILLprice_free_pricing_info (p->pricing); /* Just to be sure */
+ p->factorok = 0; /* that p is clean. */
+
+ p2 = EGLPNUM_TYPENAME_QScopy_prob (p, "scaled_lp");
+ if (p2 == 0)
+ goto CLEANUP;
+
+ rval = EGLPNUM_TYPENAME_ILLlp_scale (p2->qslp);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (primal_or_dual == 0)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlib_optimize (p2->lp, p2->basis, p2->pricing,
+ PRIMAL_SIMPLEX, 0, p2->simplex_display,
+ &(p->itcnt));
+ }
+ else
+ {
+ rval = EGLPNUM_TYPENAME_ILLlib_optimize (p2->lp, p2->basis, p2->pricing,
+ DUAL_SIMPLEX, 0, p2->simplex_display,
+ &(p->itcnt));
+ }
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = grab_basis (p2);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (p->basis)
+ {
+ EGLPNUM_TYPENAME_ILLlp_basis_free (p->basis);
+ ILL_IFFREE (p->basis, EGLPNUM_TYPENAME_ILLlp_basis);
+ }
+ p->basis = p2->basis;
+ p2->basis = 0;
+ EGLPNUM_TYPENAME_QSfree_prob (p2);
+ p2 = 0;
+ }
+
+ if (primal_or_dual == 0)
+ {
+ if (p->factorok == 0)
+ {
+ if (p->basis == 0)
+ p->lp->basisid = -1;
+ rval = EGLPNUM_TYPENAME_ILLlib_optimize (p->lp, p->basis, p->pricing, PRIMAL_SIMPLEX,
+ &rstatus, p->simplex_display, &(p->itcnt));
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_ILLprice_free_pricing_info (p->pricing);
+ if (p->lp->basisid != -1)
+ p->lp->fbasisid = p->lp->basisid;
+ rval = EGLPNUM_TYPENAME_ILLlib_optimize (p->lp, 0, p->pricing,
+ PRIMAL_SIMPLEX, &rstatus, p->simplex_display,
+ &(p->itcnt));
+ }
+ }
+ else
+ {
+ if (p->factorok == 0)
+ {
+ if (p->basis == 0)
+ p->lp->basisid = -1;
+ rval = EGLPNUM_TYPENAME_ILLlib_optimize (p->lp, p->basis, p->pricing, DUAL_SIMPLEX,
+ &rstatus, p->simplex_display, &(p->itcnt));
+ }
+ else
+ {
+ /* The factorization and rownorms should be up-to-date */
+ if (p->lp->basisid != -1)
+ {
+ p->lp->fbasisid = p->lp->basisid;
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_ILLprice_free_pricing_info (p->pricing);
+ }
+ rval = EGLPNUM_TYPENAME_ILLlib_optimize (p->lp, 0, p->pricing,
+ DUAL_SIMPLEX, &rstatus, p->simplex_display,
+ &(p->itcnt));
+ }
+ }
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = grab_basis (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (rstatus == QS_LP_OPTIMAL)
+ {
+ rval = EGLPNUM_TYPENAME_QSgrab_cache (p, rstatus);
+ CHECKRVALG (rval, CLEANUP);
+ }
+ else
+ {
+ free_cache (p);
+ }
+
+ p->factorok = 1;
+
+#if 0
+ p->lp->basisid = -1; /* This will cause the basis to be reloaded at the */
+ /* next optimization - it could be moved into the */
+ /* add/del routines if we want to cache the */
+ /* factored basis. */
+ -switched to having qs_simplex load a basis whenever it is passed;
+ the trouble with keeping basisid == -1 is that the QS - level routines
+ will not know if the
+ current lp has been optimized (so, for example,
+ getbasis will not work)
+ .
+#endif
+ CLEANUP:p->qstatus = rstatus;
+
+ if (status)
+ *status = rstatus;
+
+ if (p2)
+ EGLPNUM_TYPENAME_QSfree_prob (p2);
+ if (rval == QS_LP_CHANGE_PREC)
+ {
+ MESSAGE (__QS_SB_VERB, "Changing precision");
+ return rval;
+ }
+ MESSAGE (rval ? 0 : 1000, "Error code %d", rval);
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSopt_pivotin_row (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int rcnt,
+ int *rlist)
+{
+ int basismod = 0;
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (p->pricing == 0)
+ {
+ ILL_ERROR (rval, "pricing info not available in EGLPNUM_TYPENAME_QSopt_pivotin_row\n");
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLsimplex_pivotin (p->lp, p->pricing, rcnt, rlist,
+ SIMPLEX_PIVOTINROW, &basismod);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = grab_basis (p);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSopt_pivotin_col (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int ccnt,
+ int *clist)
+{
+ int basismod = 0;
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (p->pricing == 0)
+ {
+ ILL_ERROR (rval, "pricing info not available in QSopt_pivotin\n");
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLsimplex_pivotin (p->lp, p->pricing, ccnt, clist,
+ SIMPLEX_PIVOTINCOL, &basismod);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = grab_basis (p);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSopt_strongbranch (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int ncand,
+ int *candidatelist,
+ EGLPNUM_TYPE * xlist,
+ EGLPNUM_TYPE * down_vals,
+ EGLPNUM_TYPE * up_vals,
+ int iterations,
+ EGLPNUM_TYPE objbound)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (p->pricing == 0)
+ {
+ rval = 1;
+ CHECKRVALG (rval, CLEANUP);
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLlib_strongbranch (p->lp, p->pricing, candidatelist, ncand,
+ xlist, down_vals, up_vals, iterations, objbound,
+ &(p->itcnt));
+ CHECKRVALG (rval, CLEANUP);
+
+ p->factorok = 0;
+ free_cache (p);
+ p->qstatus = QS_LP_UNSOLVED; /* Was set to MODIFIED in free_cache () */
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSdata *EGLPNUM_TYPENAME_QScreate_prob (
+ const char *name,
+ int objsense)
+{
+ int rval = 0;
+ EGLPNUM_TYPENAME_QSdata *p = 0;
+ int len;
+
+ ILL_SAFE_MALLOC (p, 1, EGLPNUM_TYPENAME_QSdata);
+ if (!p)
+ {
+ QSlog("out of memory in EGLPNUM_TYPENAME_QScreate_prob");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ p->qslp = 0;
+ p->lp = 0;
+ p->pricing = 0;
+ p->basis = 0;
+ p->cache = 0;
+ p->qstatus = QS_LP_UNSOLVED;
+ p->factorok = 0;
+
+ p->itcnt.pI_iter = 0;
+ p->itcnt.pII_iter = 0;
+ p->itcnt.dI_iter = 0;
+ p->itcnt.dII_iter = 0;
+ p->itcnt.tot_iter = 0;
+ EGLPNUM_TYPENAME_EGlpNumInitVar(p->uobjlim);
+ EGLPNUM_TYPENAME_EGlpNumInitVar(p->lobjlim);
+ EGLPNUM_TYPENAME_EGlpNumCopy(p->uobjlim, EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+ EGLPNUM_TYPENAME_EGlpNumCopy(p->lobjlim, EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+
+ p->simplex_display = 0;
+ p->simplex_scaling = 1;
+
+ ILL_SAFE_MALLOC (p->qslp, 1, EGLPNUM_TYPENAME_ILLlpdata);
+ if (!p->qslp)
+ {
+ QSlog("out of memory in EGLPNUM_TYPENAME_QScreate_prob");
+ rval = 1;
+ goto CLEANUP;
+ }
+ EGLPNUM_TYPENAME_ILLlpdata_init (p->qslp);
+
+ ILL_SAFE_MALLOC (p->lp, 1, EGLPNUM_TYPENAME_lpinfo);
+ if (!p->lp)
+ {
+ QSlog("out of memory in EGLPNUM_TYPENAME_QScreate_prob");
+ rval = 1;
+ goto CLEANUP;
+ }
+ EGLPNUM_TYPENAME_EGlpNumInitVar (p->lp->objval);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (p->lp->pobjval);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (p->lp->dobjval);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (p->lp->pinfeas);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (p->lp->dinfeas);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (p->lp->objbound);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (p->lp->upd.piv);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (p->lp->upd.dty);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (p->lp->upd.c_obj);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (p->lp->upd.tz);
+ EGLPNUM_TYPENAME_ILLsimplex_init_lpinfo (p->lp);
+ EGLPNUM_TYPENAME_ILLsimplex_load_lpinfo (p->qslp, p->lp);
+
+ ILL_SAFE_MALLOC (p->pricing, 1, EGLPNUM_TYPENAME_price_info);
+ if (!p->pricing)
+ {
+ QSlog("out of memory in EGLPNUM_TYPENAME_QScreate_prob");
+ rval = 1;
+ goto CLEANUP;
+ }
+ EGLPNUM_TYPENAME_EGlpNumInitVar (p->pricing->htrigger);
+ EGLPNUM_TYPENAME_ILLprice_init_pricing_info (p->pricing);
+ p->pricing->pI_price = QS_DEFAULT_PRICE_PI;
+ p->pricing->pII_price = QS_DEFAULT_PRICE_PII;
+ p->pricing->dI_price = QS_DEFAULT_PRICE_DI;
+ p->pricing->dII_price = QS_DEFAULT_PRICE_DII;
+
+ if (name)
+ {
+ len = strlen (name) + 1;
+ ILL_SAFE_MALLOC (p->name, len, char);
+
+ strcpy (p->name, name);
+ }
+ else
+ {
+ ILL_SAFE_MALLOC (p->name, 7, char);
+
+ sprintf (p->name, "noname");
+ }
+
+ len = strlen (p->name) + 1;
+ ILL_SAFE_MALLOC (p->qslp->probname, len, char);
+
+ strcpy (p->qslp->probname, p->name);
+
+ if (objsense == QS_MAX)
+ {
+ p->qslp->objsense = QS_MAX;
+ }
+
+CLEANUP:
+
+ if (rval)
+ {
+ EGLPNUM_TYPENAME_QSfree_prob (p);
+ p = 0;
+ }
+
+ return p;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSdata *EGLPNUM_TYPENAME_QSread_prob (
+ const char *filename,
+ const char *filetype)
+{
+ EGLPNUM_TYPENAME_QSdata *p = 0;
+ EGioFile_t *file = 0;
+ EGLPNUM_TYPENAME_QSline_reader reader;
+
+ if ((file = EGioOpen (filename, "r")) == 0)
+ {
+ perror (filename);
+ QSlog("Unable to open \"%s\" for input.", filename);
+ }
+ if (file == NULL)
+ goto CLEANUP;
+
+ reader = EGLPNUM_TYPENAME_ILLline_reader_new ((EGLPNUM_TYPENAME_qsread_line_fct) EGioGets, file);
+ p = EGLPNUM_TYPENAME_QSget_prob (reader, filename, filetype);
+ EGLPNUM_TYPENAME_QSline_reader_free (reader); /* Bico - 040723 */
+
+CLEANUP:
+ if (file != NULL)
+ {
+ EGioClose (file);
+ }
+ return p;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSdata *EGLPNUM_TYPENAME_QSload_prob (
+ const char *probname,
+ int ncols,
+ int nrows,
+ int *cmatcnt,
+ int *cmatbeg,
+ int *cmatind,
+ EGLPNUM_TYPE * cmatval,
+ int objsense,
+ EGLPNUM_TYPE * obj,
+ EGLPNUM_TYPE * rhs,
+ char *sense,
+ EGLPNUM_TYPE * lower,
+ EGLPNUM_TYPE * upper,
+ const char **colnames,
+ const char **rownames)
+{
+ int rval = 0;
+ EGLPNUM_TYPENAME_QSdata *p = 0;
+
+ p = EGLPNUM_TYPENAME_QScreate_prob (probname, objsense);
+ if (p == 0)
+ goto CLEANUP;
+
+ rval = EGLPNUM_TYPENAME_ILLlib_newrows (p->lp, 0, nrows, rhs, sense, 0, rownames);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_addcols (p->lp, 0, ncols, cmatcnt, cmatbeg, cmatind,
+ cmatval, obj, lower, upper, colnames, 0);
+ CHECKRVALG (rval, CLEANUP);
+
+ p->factorok = 0;
+
+CLEANUP:
+
+ if (rval)
+ {
+ EGLPNUM_TYPENAME_QSfree_prob (p);
+ p = 0;
+ }
+
+ return p;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSdata *EGLPNUM_TYPENAME_QScopy_prob (
+ EGLPNUM_TYPENAME_QSdata * p,
+ const char *newname)
+{
+ int rval = 0;
+ int j, col, beg, pindex, hit;
+ EGLPNUM_TYPENAME_QSdata *p2 = 0;
+ char *coln;
+ char buf[ILL_namebufsize];
+
+ /* QSlog("EGLPNUM_TYPENAME_QScopy_prob ..."); */
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ p2 = EGLPNUM_TYPENAME_QScreate_prob (newname, p->qslp->objsense);
+ if (p2 == 0)
+ goto CLEANUP;
+
+ rval = EGLPNUM_TYPENAME_ILLlib_newrows (p2->lp, 0, p->qslp->nrows,
+ p->qslp->rhs, p->qslp->sense, p->qslp->rangeval,
+ (const char **) p->qslp->rownames);
+ CHECKRVALG (rval, CLEANUP);
+
+ for (j = 0; j < p->qslp->nstruct; j++)
+ {
+ col = p->qslp->structmap[j];
+ if (p->qslp->colnames)
+ coln = p->qslp->colnames[j];
+ else
+ coln = 0;
+ beg = p->qslp->A.matbeg[col];
+
+ /* Monika: Note that Java will need to handle these arrays */
+ /* without using the beg offset. The easiest way */
+ /* may be to copy the arrays, as in the getcols() */
+ /* code in lib.c. */
+
+ rval = EGLPNUM_TYPENAME_ILLlib_addcol (p2->lp, 0,
+ p->qslp->A.matcnt[col],
+ p->qslp->A.matind + beg, p->qslp->A.matval + beg,
+ p->qslp->obj[col], p->qslp->lower[col],
+ p->qslp->upper[col], coln, 0);
+ CHECKRVALG (rval, CLEANUP);
+ }
+
+ p2->qslp->objsense = p->qslp->objsense;
+
+ p2->factorok = 0;
+ p2->simplex_display = p->simplex_display;
+ p2->simplex_scaling = p->simplex_scaling;
+ EGLPNUM_TYPENAME_EGlpNumClearVar (p2->pricing->htrigger);
+ *(p2->pricing) = *(p->pricing);
+ /* I added this line because copying the EGLPNUM_TYPENAME_heap (as a pointer) doesn't make any
+ * sense ! */
+ EGLPNUM_TYPENAME_ILLheap_init (&(p2->pricing->h));
+ EGLPNUM_TYPENAME_EGlpNumInitVar (p2->pricing->htrigger);
+ EGLPNUM_TYPENAME_EGlpNumCopy (p2->pricing->htrigger, p->pricing->htrigger);
+
+ if (p->qslp->intmarker != 0)
+ {
+ ILL_SAFE_MALLOC (p2->qslp->intmarker, p->qslp->nstruct, char);
+
+ for (j = 0; j < p->qslp->nstruct; j++)
+ {
+ p2->qslp->intmarker[j] = p->qslp->intmarker[j];
+ }
+ }
+
+ if (p->qslp->objname != 0)
+ {
+ ILL_UTIL_STR (p2->qslp->objname, p->qslp->objname);
+ }
+ else
+ {
+ strcpy (buf, "obj");
+ rval = ILLsymboltab_uname (&p2->qslp->rowtab, buf, "", NULL);
+ CHECKRVALG (rval, CLEANUP);
+ ILL_UTIL_STR (p2->qslp->objname, buf);
+ }
+ rval = ILLsymboltab_register (&p2->qslp->rowtab, p2->qslp->objname,
+ -1, &pindex, &hit);
+ rval = rval || hit;
+ CHECKRVALG (rval, CLEANUP);
+
+ ILLstring_reporter_copy (&p2->qslp->reporter, &p->qslp->reporter);
+
+CLEANUP:
+
+ if (rval)
+ {
+ EGLPNUM_TYPENAME_QSfree_prob (p2);
+ p2 = 0;
+ }
+
+ return p2;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSchange_objsense (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int newsense)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (newsense != QS_MIN && newsense != QS_MAX)
+ {
+ QSlog("Illegal objective sense %d", newsense);
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ if (p->qslp->objsense != newsense)
+ {
+ if(newsense == QS_MAX) EGLPNUM_TYPENAME_ILLsimplex_set_bound(p->lp,(const EGLPNUM_TYPE *)(&(p->lobjlim)), newsense);
+ else EGLPNUM_TYPENAME_ILLsimplex_set_bound(p->lp,(const EGLPNUM_TYPE*)(&(p->uobjlim)), newsense);
+ p->qslp->objsense = newsense;
+ free_cache (p);
+ }
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int
+EGLPNUM_TYPENAME_QSget_itcnt(
+ EGLPNUM_TYPENAME_QSdata* p,
+ int *pI_iter,
+ int *pII_iter,
+ int *dI_iter,
+ int *dII_iter,
+ int *tot_iter)
+{
+ int rval = 0;
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+ if(pI_iter) *pI_iter = p->itcnt.pI_iter;
+ if(pII_iter) *pII_iter = p->itcnt.pII_iter;
+ if(dI_iter) *dI_iter = p->itcnt.dI_iter;
+ if(dII_iter) *dII_iter = p->itcnt.dII_iter;
+ if(tot_iter) *tot_iter = p->itcnt.tot_iter;
+
+CLEANUP:
+
+ EG_RETURN(rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_objsense (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int *objsense)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (objsense)
+ *objsense = p->qslp->objsense;
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSnew_col (
+ EGLPNUM_TYPENAME_QSdata * p,
+ const EGLPNUM_TYPE obj,
+ const EGLPNUM_TYPE lower,
+ const EGLPNUM_TYPE upper,
+ const char *name)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_newcol (p->lp, p->basis, obj, lower, upper, name, p->factorok);
+ CHECKRVALG (rval, CLEANUP);
+
+ free_cache (p);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSadd_cols (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int num,
+ int *cmatcnt,
+ int *cmatbeg,
+ int *cmatind,
+ EGLPNUM_TYPE * cmatval,
+ EGLPNUM_TYPE * obj,
+ EGLPNUM_TYPE * lower,
+ EGLPNUM_TYPE * upper,
+ const char **names)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_addcols (p->lp, p->basis, num, cmatcnt, cmatbeg,
+ cmatind, cmatval, obj, lower, upper, names,
+ p->factorok);
+ CHECKRVALG (rval, CLEANUP);
+
+ free_cache (p);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSadd_col (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int cnt,
+ int *cmatind,
+ EGLPNUM_TYPE * cmatval,
+ EGLPNUM_TYPE obj,
+ EGLPNUM_TYPE lower,
+ EGLPNUM_TYPE upper,
+ const char *name)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_addcol (p->lp, p->basis, cnt, cmatind, cmatval,
+ obj, lower, upper, name, p->factorok);
+ CHECKRVALG (rval, CLEANUP);
+
+ free_cache (p);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSnew_row (
+ EGLPNUM_TYPENAME_QSdata * p,
+ const EGLPNUM_TYPE rhs,
+ int sense,
+ const char *name)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_newrow (p->lp, p->basis, rhs, sense, EGLPNUM_TYPENAME_zeroLpNum, name);
+ CHECKRVALG (rval, CLEANUP);
+
+ p->factorok = 0;
+ free_cache (p);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSadd_ranged_rows (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int num,
+ int *rmatcnt,
+ int *rmatbeg,
+ int *rmatind,
+ const EGLPNUM_TYPE * rmatval,
+ const EGLPNUM_TYPE * rhs,
+ char *sense,
+ const EGLPNUM_TYPE * range,
+ const char **names)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_addrows (p->lp, p->basis, num, rmatcnt, rmatbeg,
+ rmatind, rmatval, rhs, sense, range,
+ names, &(p->factorok));
+ CHECKRVALG (rval, CLEANUP);
+
+ if (p->factorok == 1 && p->basis->rownorms)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlib_loadrownorms (p->lp, p->pricing, p->basis->rownorms);
+ CHECKRVALG (rval, CLEANUP);
+ /* This really should go inside of EGLPNUM_TYPENAME_ILLlib_addrows, once pinf is */
+ /* is moved into the lp struct. */
+ }
+
+ free_cache (p);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSadd_ranged_row (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int cnt,
+ int *rmatind,
+ const EGLPNUM_TYPE * rmatval,
+ const EGLPNUM_TYPE * rhs,
+ int sense,
+ const EGLPNUM_TYPE * range,
+ const char *name)
+{
+ int rval = 0;
+ int vmatcnt[1];
+ int vmatbeg[1];
+ char vsense[1];
+ const char *vnames[1];
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ vmatcnt[0] = cnt;
+ vmatbeg[0] = 0;
+ vsense[0] = sense;
+ vnames[0] = name;
+
+ rval = EGLPNUM_TYPENAME_QSadd_ranged_rows (p, 1, vmatcnt, vmatbeg, rmatind, rmatval, rhs,
+ vsense, range, vnames);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSadd_rows (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int num,
+ int *rmatcnt,
+ int *rmatbeg,
+ int *rmatind,
+ const EGLPNUM_TYPE * rmatval,
+ const EGLPNUM_TYPE * rhs,
+ char *sense,
+ const char **names)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_addrows (p->lp, p->basis, num, rmatcnt, rmatbeg,
+ rmatind, rmatval, rhs, sense, 0, names,
+ &(p->factorok));
+ CHECKRVALG (rval, CLEANUP);
+
+ if (p->factorok == 1 && p->basis->rownorms)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlib_loadrownorms (p->lp, p->pricing, p->basis->rownorms);
+ CHECKRVALG (rval, CLEANUP);
+ /* This really should go inside of EGLPNUM_TYPENAME_ILLlib_addrows, once pinf is */
+ /* is moved into the lp struct. */
+ }
+
+ free_cache (p);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSadd_row (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int cnt,
+ int *rmatind,
+ const EGLPNUM_TYPE * rmatval,
+ const EGLPNUM_TYPE * rhs,
+ int sense,
+ const char *name)
+{
+ int rval = 0;
+ int vmatcnt[1];
+ int vmatbeg[1];
+ char vsense[1];
+ const char *vnames[1];
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ vmatcnt[0] = cnt;
+ vmatbeg[0] = 0;
+ vsense[0] = sense;
+ vnames[0] = name;
+
+ rval = EGLPNUM_TYPENAME_QSadd_rows (p, 1, vmatcnt, vmatbeg, rmatind, rmatval, rhs, vsense,
+ vnames);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSdelete_rows (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int num,
+ int *dellist)
+{
+ int rval = 0;
+ int basis_ok = 0;
+ int cache_ok = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_delrows (p->lp, p->basis, p->cache, num, dellist, &basis_ok,
+ &cache_ok);
+ CHECKRVALG (rval, CLEANUP);
+
+ /* For now, just remove the basis - wait for pivotin */
+
+ if (p->basis && !basis_ok)
+ {
+ EGLPNUM_TYPENAME_ILLlp_basis_free (p->basis);
+ ILL_IFFREE (p->basis, EGLPNUM_TYPENAME_ILLlp_basis);
+ }
+
+ p->factorok = 0;
+
+ if (!p->basis || !basis_ok || !cache_ok)
+ {
+ /* Note: If we only delete basic rows then cached soln is valid */
+ free_cache (p);
+ }
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSdelete_row (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int rowindex)
+{
+ int rval = 0;
+ int vdellist[1];
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ vdellist[0] = rowindex;
+
+ rval = EGLPNUM_TYPENAME_QSdelete_rows (p, 1, vdellist);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSdelete_setrows (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int *flags)
+{
+ int rval = 0;
+ int j, num = 0;
+ int *dellist = 0;
+ int nrows;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ nrows = p->qslp->nrows;
+
+ for (j = 0; j < nrows; j++)
+ {
+ if (flags[j] == 1)
+ num++;
+ }
+
+ if (num > 0)
+ {
+ ILL_SAFE_MALLOC (dellist, num, int);
+
+ for (j = 0, num = 0; j < nrows; j++)
+ {
+ if (flags[j] == 1)
+ {
+ dellist[num++] = j;
+ }
+ }
+
+ rval = EGLPNUM_TYPENAME_QSdelete_rows (p, num, dellist);
+ CHECKRVALG (rval, CLEANUP);
+ }
+
+CLEANUP:
+
+ ILL_IFFREE (dellist, int);
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSdelete_named_row (
+ EGLPNUM_TYPENAME_QSdata * p,
+ const char *rowname)
+{
+ int rval = 0;
+ int i, vdellist[1];
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_QSget_row_index (p, rowname, &i);
+ CHECKRVALG (rval, CLEANUP);
+
+ vdellist[0] = i;
+
+ rval = EGLPNUM_TYPENAME_QSdelete_rows (p, 1, vdellist);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSdelete_named_rows_list (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int num,
+ const char **rownames)
+{
+ int rval = 0;
+ int i, k;
+ int *vdellist = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (num > 0)
+ {
+ ILL_SAFE_MALLOC (vdellist, num, int);
+
+ for (k = 0; k < num; k++)
+ {
+ rval = EGLPNUM_TYPENAME_QSget_row_index (p, rownames[k], &i);
+ CHECKRVALG (rval, CLEANUP);
+ vdellist[k] = i;
+ }
+
+ rval = EGLPNUM_TYPENAME_QSdelete_rows (p, num, vdellist);
+ CHECKRVALG (rval, CLEANUP);
+ }
+
+CLEANUP:
+
+ ILL_IFFREE (vdellist, int);
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSdelete_cols (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int num,
+ int *dellist)
+{
+ int rval = 0;
+ int basis_ok;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_delcols (p->lp, p->basis, num, dellist, &basis_ok);
+ CHECKRVALG (rval, CLEANUP);
+
+ /* For now, just remove the basis - wait for pivotout */
+
+ if (p->basis && !basis_ok)
+ {
+ EGLPNUM_TYPENAME_ILLlp_basis_free (p->basis);
+ ILL_IFFREE (p->basis, EGLPNUM_TYPENAME_ILLlp_basis);
+ }
+
+ p->factorok = 0;
+ free_cache (p);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSdelete_col (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int colindex)
+{
+ int rval = 0;
+ int vdellist[1];
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ vdellist[0] = colindex;
+
+ rval = EGLPNUM_TYPENAME_QSdelete_cols (p, 1, vdellist);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSdelete_setcols (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int *flags)
+{
+ int rval = 0;
+ int j, num = 0;
+ int *dellist = 0;
+ int ncols;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ ncols = p->qslp->nstruct;
+
+ for (j = 0; j < ncols; j++)
+ {
+ if (flags[j] == 1)
+ num++;
+ }
+
+ if (num > 0)
+ {
+ ILL_SAFE_MALLOC (dellist, num, int);
+
+ for (j = 0, num = 0; j < ncols; j++)
+ {
+ if (flags[j] == 1)
+ {
+ dellist[num++] = j;
+ }
+ }
+
+ rval = EGLPNUM_TYPENAME_QSdelete_cols (p, num, dellist);
+ CHECKRVALG (rval, CLEANUP);
+ }
+
+CLEANUP:
+
+ ILL_IFFREE (dellist, int);
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSdelete_named_column (
+ EGLPNUM_TYPENAME_QSdata * p,
+ const char *colname)
+{
+ int rval = 0;
+ int j, vdellist[1];
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_QSget_column_index (p, colname, &j);
+ CHECKRVALG (rval, CLEANUP);
+
+ vdellist[0] = j;
+
+ rval = EGLPNUM_TYPENAME_QSdelete_cols (p, 1, vdellist);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSdelete_named_columns_list (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int num,
+ const char **colnames)
+{
+ int rval = 0;
+ int i, j;
+ int *vdellist = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (num > 0)
+ {
+ ILL_SAFE_MALLOC (vdellist, num, int);
+
+ for (i = 0; i < num; i++)
+ {
+ rval = EGLPNUM_TYPENAME_QSget_column_index (p, colnames[i], &j);
+ CHECKRVALG (rval, CLEANUP);
+ vdellist[i] = j;
+ }
+
+ rval = EGLPNUM_TYPENAME_QSdelete_cols (p, num, vdellist);
+ CHECKRVALG (rval, CLEANUP);
+ }
+
+CLEANUP:
+
+ ILL_IFFREE (vdellist, int);
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSchange_senses (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int num,
+ int *rowlist,
+ char *sense)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_chgsense (p->lp, num, rowlist, sense);
+ CHECKRVALG (rval, CLEANUP);
+
+ free_cache (p);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSchange_range (
+ EGLPNUM_TYPENAME_QSdata*p,
+ int rowindex,
+ EGLPNUM_TYPE range)
+{
+ int rval = 0;
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG(rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_chgrange (p->lp, rowindex, range);
+ CHECKRVALG(rval, CLEANUP);
+
+ p->factorok = 0; /* Sanjeeb -- 050911 */
+ free_cache (p);
+
+CLEANUP:
+
+ EG_RETURN(rval);
+
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSchange_sense (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int rowindex,
+ int sense)
+{
+ int rval = 0;
+ int vrowlist[1];
+ char vsenselist[1];
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ vrowlist[0] = rowindex;
+ vsenselist[0] = sense;
+
+ rval = EGLPNUM_TYPENAME_QSchange_senses (p, 1, vrowlist, vsenselist);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_coef (
+ EGLPNUM_TYPENAME_QSdata *p,
+ int rowindex,
+ int colindex,
+ EGLPNUM_TYPE* coef)
+{
+ int rval = 0;
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+ rval = EGLPNUM_TYPENAME_ILLlib_getcoef (p->lp, rowindex, colindex, coef);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSchange_coef (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int rowindex,
+ int colindex,
+ EGLPNUM_TYPE coef)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_chgcoef (p->lp, rowindex, colindex, coef);
+ CHECKRVALG (rval, CLEANUP);
+
+ free_cache (p);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSchange_objcoef (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int indx,
+ EGLPNUM_TYPE coef)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_chgobj (p->lp, indx, coef);
+ CHECKRVALG (rval, CLEANUP);
+
+ free_cache (p);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSchange_rhscoef (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int indx,
+ EGLPNUM_TYPE coef)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_chgrhs (p->lp, indx, coef);
+ CHECKRVALG (rval, CLEANUP);
+
+ free_cache (p);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSchange_bounds (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int num,
+ int *collist,
+ char *lu,
+ const EGLPNUM_TYPE * bounds)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_chgbnds (p->lp, num, collist, lu, bounds);
+ CHECKRVALG (rval, CLEANUP);
+
+ free_cache (p);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSchange_bound (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int indx,
+ int lu,
+ const EGLPNUM_TYPE bound)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_chgbnd (p->lp, indx, lu, bound);
+ CHECKRVALG (rval, CLEANUP);
+
+ free_cache (p);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+#if 0
+ /*
+ * Bico - I removed this on 02.04.22. I don't think we need to support
+ * this type of interface (the loading via arrays can do the job)
+ */
+EGLPNUM_TYPENAME_QSLIB_INTERFACE QSbasis *QScreate_basis (
+ int nstruct,
+ int nrows)
+{
+ int rval = 0;
+ int i;
+ QSbasis *B = 0;
+
+ ILL_SAFE_MALLOC (B, 1, QSbasis);
+
+ B->nstruct = nstruct;
+ B->nrows = nrows;
+ B->cstat = 0;
+ B->rstat = 0;
+
+ if (nstruct)
+ {
+ ILL_SAFE_MALLOC (B->cstat, nstruct, char);
+ }
+
+ if (nrows)
+ {
+ ILL_SAFE_MALLOC (B->rstat, nrows, char);
+ }
+
+ for (i = 0; i < nstruct; i++)
+ B->cstat[i] = 0;
+ for (i = 0; i < nrows; i++)
+ B->rstat[i] = 0;
+
+CLEANUP:
+
+ if (rval)
+ {
+ EGLPNUM_TYPENAME_QSfree_basis (B);
+ B = 0;
+ }
+
+ return B;
+}
+#endif
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE QSbasis *EGLPNUM_TYPENAME_QSread_basis (
+ EGLPNUM_TYPENAME_QSdata * p,
+ const char *filename)
+{
+ int rval = 0;
+ QSbasis *qB = 0;
+ EGLPNUM_TYPENAME_ILLlp_basis B;
+
+ EGLPNUM_TYPENAME_ILLlp_basis_init (&B);
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ ILL_NEW (qB, QSbasis);
+ init_basis (qB);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_readbasis (p->lp, &B, filename);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = illbasis_to_qsbasis (&B, qB);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ if (rval && qB)
+ {
+ EGLPNUM_TYPENAME_QSfree_basis (qB);
+ qB = 0;
+ }
+ EGLPNUM_TYPENAME_ILLlp_basis_free (&B);
+
+ return qB;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSload_basis (
+ EGLPNUM_TYPENAME_QSdata * p,
+ QSbasis * B)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (B->nstruct != p->qslp->nstruct || B->nrows != p->qslp->nrows)
+ {
+ QSlog("size of basis does not match lp");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ if (p->basis == 0)
+ {
+ ILL_SAFE_MALLOC (p->basis, 1, EGLPNUM_TYPENAME_ILLlp_basis);
+ EGLPNUM_TYPENAME_ILLlp_basis_init (p->basis);
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_ILLlp_basis_free (p->basis);
+ }
+
+ rval = qsbasis_to_illbasis (B, p->basis);
+ CHECKRVALG (rval, CLEANUP);
+
+ p->factorok = 0;
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSread_and_load_basis (
+ EGLPNUM_TYPENAME_QSdata * p,
+ const char *filename)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (p->basis == 0)
+ {
+ ILL_SAFE_MALLOC (p->basis, 1, EGLPNUM_TYPENAME_ILLlp_basis);
+ EGLPNUM_TYPENAME_ILLlp_basis_init (p->basis);
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_ILLlp_basis_free (p->basis);
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLlib_readbasis (p->lp, p->basis, filename);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ return rval;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSload_basis_array (
+ EGLPNUM_TYPENAME_QSdata * p,
+ char *cstat,
+ char *rstat)
+{
+ int rval = 0;
+ int i;
+ EGLPNUM_TYPENAME_ILLlp_basis *B;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ qslp = p->qslp;
+
+ if (qslp->nstruct > 0 && cstat == 0)
+ {
+ QSlog("EGLPNUM_TYPENAME_QSload_basis_array called without cstat");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ if (qslp->nrows > 0 && rstat == 0)
+ {
+ QSlog("EGLPNUM_TYPENAME_QSload_basis_array called without rstat");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ if (p->basis == 0)
+ {
+ ILL_SAFE_MALLOC (p->basis, 1, EGLPNUM_TYPENAME_ILLlp_basis);
+ EGLPNUM_TYPENAME_ILLlp_basis_init (p->basis);
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_ILLlp_basis_free (p->basis);
+ }
+
+ B = p->basis;
+
+ B->nstruct = qslp->nstruct;
+ B->nrows = qslp->nrows;
+ ILL_SAFE_MALLOC (B->cstat, qslp->nstruct, char);
+ ILL_SAFE_MALLOC (B->rstat, qslp->nrows, char);
+
+ for (i = 0; i < qslp->nstruct; i++)
+ {
+ B->cstat[i] = cstat[i];
+ }
+
+ for (i = 0; i < qslp->nrows; i++)
+ {
+ B->rstat[i] = rstat[i];
+ }
+
+ p->factorok = 0;
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSload_basis_and_row_norms_array (
+ EGLPNUM_TYPENAME_QSdata * p,
+ char *cstat,
+ char *rstat,
+ EGLPNUM_TYPE * rownorms)
+{
+ int rval = 0;
+ int i, nrows;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ nrows = p->qslp->nrows;
+
+ rval = EGLPNUM_TYPENAME_QSload_basis_array (p, cstat, rstat);
+ CHECKRVALG (rval, CLEANUP);
+ p->basis->rownorms = EGLPNUM_TYPENAME_EGlpNumAllocArray (nrows);
+
+ for (i = 0; i < nrows; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (p->basis->rownorms[i], rownorms[i]);
+ }
+
+ p->factorok = 0;
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSwrite_basis (
+ EGLPNUM_TYPENAME_QSdata * p,
+ QSbasis * B,
+ const char *filename)
+{
+ int rval = 0;
+ EGLPNUM_TYPENAME_ILLlp_basis iB, *basis = 0;
+
+ EGLPNUM_TYPENAME_ILLlp_basis_init (&iB);
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (B)
+ {
+ rval = qsbasis_to_illbasis (B, &iB);
+ CHECKRVALG (rval, CLEANUP);
+ basis = &iB;
+ }
+ else
+ {
+ if (p->basis == 0)
+ {
+ QSlog("no basis available in EGLPNUM_TYPENAME_QSwrite_basis");
+ rval = 1;
+ goto CLEANUP;
+ }
+ basis = p->basis;
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLlib_writebasis (p->lp, basis, filename);
+ CHECKRVALG (rval, CLEANUP);
+
+
+CLEANUP:
+
+ EGLPNUM_TYPENAME_ILLlp_basis_free (basis);
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE QSbasis *EGLPNUM_TYPENAME_QSget_basis (
+ EGLPNUM_TYPENAME_QSdata * p)
+{
+ int rval = 0;
+ QSbasis *B = 0;
+
+ if (p->basis == 0)
+ {
+ QSlog("no basis available in EGLPNUM_TYPENAME_QSget_basis");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ ILL_SAFE_MALLOC (B, 1, QSbasis);
+ init_basis (B);
+ rval = illbasis_to_qsbasis (p->basis, B);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ if (rval)
+ {
+ EGLPNUM_TYPENAME_QSfree_basis (B);
+ B = 0;
+ }
+
+ return B;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_basis_array (
+ EGLPNUM_TYPENAME_QSdata * p,
+ char *cstat,
+ char *rstat)
+{
+ int rval = 0;
+ int i;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (p->basis == 0)
+ {
+ QSlog("no basis available in EGLPNUM_TYPENAME_QSget_basis_array");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ for (i = 0; i < p->basis->nstruct; i++)
+ cstat[i] = p->basis->cstat[i];
+ for (i = 0; i < p->basis->nrows; i++)
+ rstat[i] = p->basis->rstat[i];
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_basis_and_row_norms_array (
+ EGLPNUM_TYPENAME_QSdata * p,
+ char *cstat,
+ char *rstat,
+ EGLPNUM_TYPE * rownorms)
+{
+ int rval = 0;
+ int i;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (p->basis == 0)
+ {
+ QSlog("no basis available");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ for (i = 0; i < p->basis->nstruct; i++)
+ cstat[i] = p->basis->cstat[i];
+ for (i = 0; i < p->basis->nrows; i++)
+ rstat[i] = p->basis->rstat[i];
+
+ if (p->basis->rownorms == 0)
+ {
+ QSlog("no row norms available");
+ rval = 1;
+ goto CLEANUP;
+ }
+ else
+ {
+ for (i = 0; i < p->basis->nrows; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (rownorms[i], p->basis->rownorms[i]);
+ }
+ }
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+static int illbasis_to_qsbasis (
+ EGLPNUM_TYPENAME_ILLlp_basis * B,
+ QSbasis * qB)
+{
+ int rval = 0;
+ int i;
+
+ qB->nstruct = B->nstruct;
+ qB->nrows = B->nrows;
+ ILL_SAFE_MALLOC (qB->cstat, B->nstruct, char);
+ ILL_SAFE_MALLOC (qB->rstat, B->nrows, char);
+
+ for (i = 0; i < B->nstruct; i++)
+ {
+ qB->cstat[i] = B->cstat[i];
+ }
+
+ for (i = 0; i < B->nrows; i++)
+ {
+ qB->rstat[i] = B->rstat[i];
+ }
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+static int qsbasis_to_illbasis (
+ QSbasis * qB,
+ EGLPNUM_TYPENAME_ILLlp_basis * B)
+{
+ int rval = 0;
+ int i;
+ int nbas = 0;
+
+ B->nstruct = qB->nstruct;
+ B->nrows = qB->nrows;
+ ILL_SAFE_MALLOC (B->cstat, qB->nstruct, char);
+ ILL_SAFE_MALLOC (B->rstat, qB->nrows, char);
+
+ for (i = 0; i < qB->nstruct; i++)
+ {
+ if(qB->cstat[i] == QS_COL_BSTAT_BASIC) nbas++;
+ B->cstat[i] = qB->cstat[i];
+ }
+
+ for (i = 0; i < qB->nrows; i++)
+ {
+ if(qB->rstat[i] == QS_ROW_BSTAT_BASIC) nbas++;
+ B->rstat[i] = qB->rstat[i];
+ }
+
+ if(nbas != qB->nrows)
+ {
+ QSlog("Received basis is not valid, in qsbasis_to_illbasis");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+int grab_basis (
+ EGLPNUM_TYPENAME_QSdata * p)
+{
+ int rval = 0;
+ EGLPNUM_TYPENAME_ILLlp_basis *B = p->basis;
+ int nstruct = p->qslp->nstruct;
+ int nrows = p->qslp->nrows;
+
+ if (!B)
+ {
+ ILL_SAFE_MALLOC (p->basis, 1, EGLPNUM_TYPENAME_ILLlp_basis);
+ EGLPNUM_TYPENAME_ILLlp_basis_init (p->basis);
+ B = p->basis;
+ }
+
+ if (nstruct != B->nstruct)
+ {
+ ILL_IFFREE (B->cstat, char);
+ ILL_SAFE_MALLOC (B->cstat, nstruct, char);
+
+ B->nstruct = nstruct;
+ }
+
+ if (nrows != B->nrows)
+ {
+ ILL_IFFREE (B->rstat, char);
+ ILL_SAFE_MALLOC (B->rstat, nrows, char);
+
+ B->nrows = nrows;
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLlib_getbasis (p->lp, B->cstat, B->rstat);
+ CHECKRVALG (rval, CLEANUP);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (B->rownorms);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (B->colnorms);
+
+ if (p->pricing->dII_price == QS_PRICE_DSTEEP)
+ {
+ B->rownorms = EGLPNUM_TYPENAME_EGlpNumAllocArray (nrows);
+ rval = EGLPNUM_TYPENAME_ILLlib_getrownorms (p->lp, p->pricing, B->rownorms);
+ if (rval)
+ {
+/*
+ QSlog("no edge norms, continue anyway");
+*/
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (B->rownorms);
+ rval = 0;
+ }
+ }
+
+CLEANUP:
+
+ if (rval)
+ {
+ if (B)
+ {
+ EGLPNUM_TYPENAME_ILLlp_basis_free (B);
+ ILL_IFFREE (p->basis, EGLPNUM_TYPENAME_ILLlp_basis);
+ }
+ }
+
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_QSgrab_cache (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int status)
+{
+ int rval = 0;
+ EGLPNUM_TYPENAME_ILLlp_cache *C = p->cache;
+ int nstruct = p->qslp->nstruct;
+ int nrows = p->qslp->nrows;
+ #if 0
+ /* we may need to fix basic status for fixed variables */
+ register int i;
+ char *const cstat = p->basis->cstat;
+ const int *const structmap = p->lp->O->structmap;
+ const int sense = p->lp->O->objsense;
+ const int *const vtype = p->lp->vtype;
+ int *const vstat = p->lp->vstat;
+ /* end extra variables needed */
+ #endif
+
+ if (C == 0)
+ {
+ ILL_SAFE_MALLOC (p->cache, 1, EGLPNUM_TYPENAME_ILLlp_cache);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (p->cache->val);
+ EGLPNUM_TYPENAME_ILLlp_cache_init (p->cache);
+ C = p->cache;
+ }
+
+ if (nstruct != C->nstruct || nrows != C->nrows)
+ {
+ EGLPNUM_TYPENAME_ILLlp_cache_free (C);
+ rval = EGLPNUM_TYPENAME_ILLlp_cache_alloc (C, nstruct, nrows);
+ CHECKRVALG (rval, CLEANUP);
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLlib_cache_solution (p->lp, C);
+ CHECKRVALG (rval, CLEANUP);
+
+ #if 0
+ /* we fix basis status and vstat */
+ for( i = nstruct ; i-- ; )
+ {
+ if(vtype[structmap[i]] != VFIXED) continue;
+ if(cstat[i] == QS_COL_BSTAT_BASIC) continue;
+ if(( sense > 0 && EGLPNUM_TYPENAME_EGlpNumIsLess(EGLPNUM_TYPENAME_SZERO_TOLER,C->rc[i])) ||
+ ( sense < 0 && !EGLPNUM_TYPENAME_EGlpNumIsLess(EGLPNUM_TYPENAME_SZERO_TOLER,C->rc[i])))
+ {
+ vstat[structmap[i]] = STAT_LOWER;
+ cstat[i] = QS_COL_BSTAT_LOWER;
+ }
+ else
+ {
+ vstat[structmap[i]] = STAT_UPPER;
+ cstat[i] = QS_COL_BSTAT_UPPER;
+ }
+ }/* end fix */
+ #endif
+ C->status = status;
+
+CLEANUP:
+
+ if (rval)
+ {
+ if (C)
+ {
+ EGLPNUM_TYPENAME_ILLlp_cache_free (C);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (p->cache->val);
+ ILL_IFFREE (p->cache, EGLPNUM_TYPENAME_ILLlp_cache);
+ }
+ }
+
+ EG_RETURN (rval);
+}
+
+void free_cache (
+ EGLPNUM_TYPENAME_QSdata * p)
+{
+ if (p->cache)
+ {
+ EGLPNUM_TYPENAME_ILLlp_cache_free (p->cache);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (p->cache->val);
+ ILL_IFFREE (p->cache, EGLPNUM_TYPENAME_ILLlp_cache);
+ }
+ p->qstatus = QS_LP_MODIFIED;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_binv_row (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int indx,
+ EGLPNUM_TYPE * binvrow)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if(!p->basis)
+ {
+ QSlog("no active basis in store");
+ rval = 1;
+ goto CLEANUP;
+ }
+ if(0>indx || indx >= EGLPNUM_TYPENAME_QSget_rowcount(p))
+ {
+ QSlog("row index %d outside valid bounds [%d:%d]",
+ indx, 0, EGLPNUM_TYPENAME_QSget_rowcount(p)-1);
+ rval = 1;
+ goto CLEANUP;
+ }
+ if (p->cache == 0)
+ {
+ QSlog("LP has not been optimized in EGLPNUM_TYPENAME_QSget_binv_row");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLlib_tableau (p->lp, indx, binvrow, 0);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_tableau_row (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int indx,
+ EGLPNUM_TYPE * tableaurow)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (p->cache == 0)
+ {
+ QSlog("LP has not been optimized in EGLPNUM_TYPENAME_QSget_tableau_row");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLlib_tableau (p->lp, indx, 0, tableaurow);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_basis_order (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int *basorder)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (p->cache == 0)
+ {
+ QSlog("LP has not been optimized in EGLPNUM_TYPENAME_QSget_basis_order");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLlib_basis_order (p->lp, basorder);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QScompute_row_norms (
+ EGLPNUM_TYPENAME_QSdata * p)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (p->pricing->dII_price != QS_PRICE_DSTEEP)
+ {
+ QSlog("not using dual steepest edge");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLlib_recompute_rownorms (p->lp, p->pricing);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = grab_basis (p);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSfree_prob (
+ EGLPNUM_TYPENAME_QSdata * p)
+{
+ if (p)
+ {
+ EGLPNUM_TYPENAME_EGlpNumClearVar(p->uobjlim);
+ EGLPNUM_TYPENAME_EGlpNumClearVar(p->lobjlim);
+ if (p->qslp)
+ {
+ EGLPNUM_TYPENAME_ILLlpdata_free (p->qslp);
+ ILL_IFFREE (p->qslp, EGLPNUM_TYPENAME_ILLlpdata);
+ }
+ if (p->lp)
+ {
+ EGLPNUM_TYPENAME_ILLsimplex_free_lpinfo (p->lp);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (p->lp->objval);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (p->lp->pobjval);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (p->lp->dobjval);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (p->lp->pinfeas);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (p->lp->dinfeas);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (p->lp->objbound);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (p->lp->upd.piv);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (p->lp->upd.dty);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (p->lp->upd.c_obj);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (p->lp->upd.tz);
+ ILL_IFFREE (p->lp, EGLPNUM_TYPENAME_lpinfo);
+ }
+ if (p->basis)
+ {
+ EGLPNUM_TYPENAME_ILLlp_basis_free (p->basis);
+ ILL_IFFREE (p->basis, EGLPNUM_TYPENAME_ILLlp_basis);
+ }
+ if (p->cache)
+ {
+ EGLPNUM_TYPENAME_ILLlp_cache_free (p->cache);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (p->cache->val);
+ ILL_IFFREE (p->cache, EGLPNUM_TYPENAME_ILLlp_cache);
+ }
+ if (p->pricing)
+ {
+ EGLPNUM_TYPENAME_EGlpNumClearVar (p->pricing->htrigger);
+ EGLPNUM_TYPENAME_ILLprice_free_pricing_info (p->pricing);
+ ILL_IFFREE (p->pricing, EGLPNUM_TYPENAME_price_info);
+ }
+ ILL_IFFREE (p->name, char);
+
+ ILL_IFFREE (p, EGLPNUM_TYPENAME_QSdata);
+ }
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSfree_basis (
+ QSbasis * B)
+{
+ if (B)
+ {
+ ILL_IFFREE (B->rstat, char);
+ ILL_IFFREE (B->cstat, char);
+
+ ILL_IFFREE (B, QSbasis);
+ }
+}
+
+static void init_basis (
+ QSbasis * B)
+{
+ if (B)
+ {
+ B->nstruct = 0;
+ B->nrows = 0;
+ B->cstat = 0;
+ B->rstat = 0;
+ }
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_status (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int *status)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (status)
+ *status = p->qstatus;
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_solution (
+ EGLPNUM_TYPENAME_QSdata * p,
+ EGLPNUM_TYPE * value,
+ EGLPNUM_TYPE * x,
+ EGLPNUM_TYPE * pi,
+ EGLPNUM_TYPE * slack,
+ EGLPNUM_TYPE * rc)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (p->cache == 0)
+ {
+ QSlog("no solution available in EGLPNUM_TYPENAME_QSget_solution");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLlib_solution (p->lp, p->cache, value, x, pi, slack, rc);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_objval (
+ EGLPNUM_TYPENAME_QSdata * p,
+ EGLPNUM_TYPE * value)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+/* Want to get objval after limited number of pivots. */
+
+ if (p->qstatus == QS_LP_MODIFIED)
+ {
+ QSlog("QSmsg: LP has been modified since last solve.");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLlib_objval (p->lp, p->cache, value);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_x_array (
+ EGLPNUM_TYPENAME_QSdata * p,
+ EGLPNUM_TYPE * x)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (p->cache == 0)
+ {
+ QSlog("no solution available in EGLPNUM_TYPENAME_QSget_x_array");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLlib_get_x (p->lp, p->cache, x);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_slack_array (
+ EGLPNUM_TYPENAME_QSdata * p,
+ EGLPNUM_TYPE * slack)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (p->cache == 0)
+ {
+ QSlog("no solution available in EGLPNUM_TYPENAME_QSget_slack_array");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLlib_get_slack (p->lp, p->cache, slack);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_rc_array (
+ EGLPNUM_TYPENAME_QSdata * p,
+ EGLPNUM_TYPE * rc)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (p->cache == 0)
+ {
+ QSlog("no solution available in EGLPNUM_TYPENAME_QSget_rc_array");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLlib_solution (p->lp, p->cache, 0, 0, 0, 0, rc);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_pi_array (
+ EGLPNUM_TYPENAME_QSdata * p,
+ EGLPNUM_TYPE * pi)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (p->cache == 0)
+ {
+ QSlog("no solution available in EGLPNUM_TYPENAME_QSget_pi_array");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLlib_solution (p->lp, p->cache, 0, 0, pi, 0, 0);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_infeas_array (
+ EGLPNUM_TYPENAME_QSdata * p,
+ EGLPNUM_TYPE * pi)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (pi == 0)
+ {
+ ILL_ERROR (rval, "QS_get_infeas_array called with NULL pi vector\n");
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLsimplex_infcertificate (p->lp, pi);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_named_x (
+ EGLPNUM_TYPENAME_QSdata * p,
+ const char *colname,
+ EGLPNUM_TYPE * val)
+{
+ int rval = 0;
+ int j;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (p->cache == 0)
+ {
+ QSlog("no solution available in EGLPNUM_TYPENAME_QSget_named_x");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ rval = EGLPNUM_TYPENAME_QSget_column_index (p, colname, &j);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (j != -1)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (*val, p->cache->x[j]);
+ }
+ else
+ {
+ rval = 1;
+ }
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_named_rc (
+ EGLPNUM_TYPENAME_QSdata * p,
+ const char *colname,
+ EGLPNUM_TYPE * val)
+{
+ int rval = 0;
+ int j;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (p->cache == 0)
+ {
+ QSlog("no solution available in EGLPNUM_TYPENAME_QSget_named_rc");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ rval = EGLPNUM_TYPENAME_QSget_column_index (p, colname, &j);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (j != -1)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (*val, p->cache->rc[j]);
+ }
+ else
+ {
+ rval = 1;
+ }
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_named_pi (
+ EGLPNUM_TYPENAME_QSdata * p,
+ const char *rowname,
+ EGLPNUM_TYPE * val)
+{
+ int rval = 0;
+ int i;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (p->cache == 0)
+ {
+ QSlog("no solution available in EGLPNUM_TYPENAME_QSget_named_pi");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ rval = EGLPNUM_TYPENAME_QSget_row_index (p, rowname, &i);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (i != -1)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (*val, p->cache->pi[i]);
+ }
+ else
+ {
+ rval = 1;
+ }
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_named_slack (
+ EGLPNUM_TYPENAME_QSdata * p,
+ const char *rowname,
+ EGLPNUM_TYPE * val)
+{
+ int rval = 0;
+ int i;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (p->cache == 0)
+ {
+ QSlog("no solution available in EGLPNUM_TYPENAME_QSget_named_slack");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ rval = EGLPNUM_TYPENAME_QSget_row_index (p, rowname, &i);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (i != -1)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (*val, p->cache->slack[i]);
+ }
+ else
+ {
+ rval = 1;
+ }
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_colcount (
+ EGLPNUM_TYPENAME_QSdata * p)
+{
+ int cnt;
+
+ if (check_qsdata_pointer (p))
+ cnt = 0;
+ else
+ cnt = p->qslp->nstruct;
+
+ return cnt;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_rowcount (
+ EGLPNUM_TYPENAME_QSdata * p)
+{
+ int cnt;
+
+ if (check_qsdata_pointer (p))
+ cnt = 0;
+ else
+ cnt = p->qslp->nrows;
+
+ return cnt;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_nzcount (
+ EGLPNUM_TYPENAME_QSdata * p)
+{
+ int cnt;
+
+ if (check_qsdata_pointer (p))
+ cnt = 0;
+ else
+ cnt = p->qslp->nzcount - p->qslp->nrows;
+
+ return cnt;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QStest_row_norms (
+ EGLPNUM_TYPENAME_QSdata * p)
+{
+ int yesno;
+
+ if (check_qsdata_pointer (p))
+ {
+ yesno = 0;
+ }
+ else
+ {
+ if (p->basis && p->basis->rownorms)
+ {
+ yesno = 1;
+ }
+ else
+ {
+ yesno = 0;
+ }
+ }
+
+ return yesno;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_obj_list(EGLPNUM_TYPENAME_QSprob p,
+ int num,
+ int*collist,
+ EGLPNUM_TYPE*obj)
+{
+ int rval = 0;
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+ rval = EGLPNUM_TYPENAME_ILLlib_getobj_list (p->lp, num, collist, obj);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_obj (
+ EGLPNUM_TYPENAME_QSdata * p,
+ EGLPNUM_TYPE * obj)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_getobj (p->lp, obj);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_rhs (
+ EGLPNUM_TYPENAME_QSdata * p,
+ EGLPNUM_TYPE * rhs)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_getrhs (p->lp, rhs);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_ranged_rows_list (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int num,
+ int *rowlist,
+ int **rowcnt,
+ int **rowbeg,
+ int **rowind,
+ EGLPNUM_TYPE ** rowval,
+ EGLPNUM_TYPE ** rhs,
+ char **sense,
+ EGLPNUM_TYPE ** range,
+ char ***names)
+{
+ int rval = 0;
+ int i, nrows;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ nrows = EGLPNUM_TYPENAME_QSget_rowcount (p);
+ for (i = 0; i < num; i++)
+ {
+ if (rowlist[i] < 0 || rowlist[i] >= nrows)
+ {
+ QSlog("entry %d in rowlist out of range", i);
+ rval = 1;
+ goto CLEANUP;
+ }
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLlib_getrows (p->lp, num, rowlist, rowcnt, rowbeg, rowind,
+ rowval, rhs, sense, range, names);
+ CHECKRVALG (rval, CLEANUP);
+
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_ranged_rows (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int **rowcnt,
+ int **rowbeg,
+ int **rowind,
+ EGLPNUM_TYPE ** rowval,
+ EGLPNUM_TYPE ** rhs,
+ char **sense,
+ EGLPNUM_TYPE ** range,
+ char ***names)
+{
+ int rval = 0;
+ int i, nrows;
+ int *rowlist = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ nrows = EGLPNUM_TYPENAME_QSget_rowcount (p);
+ if (nrows > 0)
+ {
+ ILL_SAFE_MALLOC (rowlist, nrows, int);
+
+ for (i = 0; i < nrows; i++)
+ {
+ rowlist[i] = i;
+ }
+ rval = EGLPNUM_TYPENAME_ILLlib_getrows (p->lp, nrows, rowlist, rowcnt, rowbeg, rowind,
+ rowval, rhs, sense, range, names);
+ CHECKRVALG (rval, CLEANUP);
+ }
+
+CLEANUP:
+
+ ILL_IFFREE (rowlist, int);
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_senses (
+ EGLPNUM_TYPENAME_QSdata *p,
+ char *senses)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_getsenses (p->lp, senses);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_rows_list (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int num,
+ int *rowlist,
+ int **rowcnt,
+ int **rowbeg,
+ int **rowind,
+ EGLPNUM_TYPE ** rowval,
+ EGLPNUM_TYPE ** rhs,
+ char **sense,
+ char ***names)
+{
+ int rval = 0;
+ int i, nrows;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ nrows = EGLPNUM_TYPENAME_QSget_rowcount (p);
+ for (i = 0; i < num; i++)
+ {
+ if (rowlist[i] < 0 || rowlist[i] >= nrows)
+ {
+ QSlog("entry %d in rowlist out of range", i);
+ rval = 1;
+ goto CLEANUP;
+ }
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLlib_getrows (p->lp, num, rowlist, rowcnt, rowbeg, rowind,
+ rowval, rhs, sense, 0, names);
+ CHECKRVALG (rval, CLEANUP);
+
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_rows (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int **rowcnt,
+ int **rowbeg,
+ int **rowind,
+ EGLPNUM_TYPE ** rowval,
+ EGLPNUM_TYPE ** rhs,
+ char **sense,
+ char ***names)
+{
+ int rval = 0;
+ int i, nrows;
+ int *rowlist = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ nrows = EGLPNUM_TYPENAME_QSget_rowcount (p);
+ if (nrows > 0)
+ {
+ ILL_SAFE_MALLOC (rowlist, nrows, int);
+
+ for (i = 0; i < nrows; i++)
+ {
+ rowlist[i] = i;
+ }
+ rval = EGLPNUM_TYPENAME_ILLlib_getrows (p->lp, nrows, rowlist, rowcnt, rowbeg, rowind,
+ rowval, rhs, sense, 0, names);
+ CHECKRVALG (rval, CLEANUP);
+ }
+
+CLEANUP:
+
+ ILL_IFFREE (rowlist, int);
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_columns_list (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int num,
+ int *collist,
+ int **colcnt,
+ int **colbeg,
+ int **colind,
+ EGLPNUM_TYPE ** colval,
+ EGLPNUM_TYPE ** obj,
+ EGLPNUM_TYPE ** lower,
+ EGLPNUM_TYPE ** upper,
+ char ***names)
+{
+ int rval = 0;
+ int j, ncols;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ ncols = EGLPNUM_TYPENAME_QSget_colcount (p);
+ for (j = 0; j < num; j++)
+ {
+ if (collist[j] < 0 || collist[j] >= ncols)
+ {
+ QSlog("entry %d in collist out of range", j);
+ rval = 1;
+ goto CLEANUP;
+ }
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLlib_getcols (p->lp, num, collist, colcnt, colbeg, colind,
+ colval, obj, lower, upper, names);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_columns (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int **colcnt,
+ int **colbeg,
+ int **colind,
+ EGLPNUM_TYPE ** colval,
+ EGLPNUM_TYPE ** obj,
+ EGLPNUM_TYPE ** lower,
+ EGLPNUM_TYPE ** upper,
+ char ***names)
+{
+ int rval = 0;
+ int j, ncols;
+ int *collist = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ ncols = EGLPNUM_TYPENAME_QSget_colcount (p);
+ if (ncols > 0)
+ {
+ ILL_SAFE_MALLOC (collist, ncols, int);
+
+ for (j = 0; j < ncols; j++)
+ {
+ collist[j] = j;
+ }
+ rval = EGLPNUM_TYPENAME_ILLlib_getcols (p->lp, ncols, collist, colcnt, colbeg, colind,
+ colval, obj, lower, upper, names);
+ CHECKRVALG (rval, CLEANUP);
+ }
+
+CLEANUP:
+
+ ILL_IFFREE (collist, int);
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE char *EGLPNUM_TYPENAME_QSget_probname (
+ EGLPNUM_TYPENAME_QSdata * p)
+{
+ int rval = 0;
+ char *name = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ ILL_UTIL_STR (name, p->name);
+
+CLEANUP:
+ ILL_RETURN_PTR (name, "EGLPNUM_TYPENAME_QSget_probname");
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE char *EGLPNUM_TYPENAME_QSget_objname (
+ EGLPNUM_TYPENAME_QSdata * p)
+{
+ int rval = 0;
+ char *name = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (p->qslp->objname != 0)
+ {
+ ILL_UTIL_STR (name, p->qslp->objname);
+ }
+
+CLEANUP:
+ ILL_RETURN_PTR (name, "EGLPNUM_TYPENAME_QSget_objname");
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_rownames (
+ EGLPNUM_TYPENAME_QSdata * p,
+ char **rownames)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_rownames (p->lp, rownames);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_colnames (
+ EGLPNUM_TYPENAME_QSdata * p,
+ char **colnames)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_colnames (p->lp, colnames);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_bound (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int colindex,
+ int lu,
+ EGLPNUM_TYPE * bound)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_getbnd (p->lp, colindex, lu, bound);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_bounds_list(
+ EGLPNUM_TYPENAME_QSdata* p,
+ int num,
+ int*collist,
+ EGLPNUM_TYPE*lb,
+ EGLPNUM_TYPE*ub)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_getbnds_list (p->lp, num, collist, lb, ub);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_bounds (
+ EGLPNUM_TYPENAME_QSdata * p,
+ EGLPNUM_TYPE * lower,
+ EGLPNUM_TYPE * upper)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_getbnds (p->lp, lower, upper);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_intflags (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int *intflags)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (intflags == 0)
+ {
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLlib_getintflags (p->lp, intflags);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_intcount (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int *count)
+{
+ int j, ncols, cnt = 0, rval = 0;
+ int *intflags = 0;
+
+ *count = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ ncols = EGLPNUM_TYPENAME_QSget_colcount (p);
+
+ if (ncols > 0)
+ {
+ ILL_SAFE_MALLOC (intflags, ncols, int);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_getintflags (p->lp, intflags);
+ CHECKRVALG (rval, CLEANUP);
+
+ for (j = 0; j < ncols; j++)
+ {
+ if (intflags[j] > 0)
+ cnt++;
+ }
+ }
+
+CLEANUP:
+
+ *count = cnt;
+ ILL_IFFREE (intflags, int);
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_column_index (
+ EGLPNUM_TYPENAME_QSdata * p,
+ const char *name,
+ int *colindex)
+{
+ int rval = 0;
+
+ *colindex = -1;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_colindex (p->lp, name, colindex);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_row_index (
+ EGLPNUM_TYPENAME_QSdata * p,
+ const char *name,
+ int *rowindex)
+{
+ int rval = 0;
+
+ *rowindex = -1;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ rval = EGLPNUM_TYPENAME_ILLlib_rowindex (p->lp, name, rowindex);
+ CHECKRVALG (rval, CLEANUP);
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+static int QSwrite_prob_EGioFile(
+ EGLPNUM_TYPENAME_QSdata*p,
+ EGioFile_t*out,
+ const char*filetype)
+{
+ int rval = 0;
+ qsstring_reporter rep;
+
+ ILLstring_reporter_copy(&rep, &p->qslp->reporter);
+ ILLstring_reporter_init(&p->qslp->reporter,
+ (qsreport_string_fct) EGioWrite, out);
+ rval = EGLPNUM_TYPENAME_QSreport_prob(p, filetype, NULL);
+ ILLstring_reporter_copy(&p->qslp->reporter, &rep);
+ ILL_RESULT(rval, "QSwrite_prob_EGioFile");
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSwrite_prob (
+ EGLPNUM_TYPENAME_QSdata * p,
+ const char *filename,
+ const char *filetype)
+{
+ EGioFile_t *file = NULL;
+ int rval = 0;
+
+ if (filename == NULL)
+ {
+ file = EGioOpenFILE(stdout);
+ }
+ else
+ {
+ if ((file = EGioOpen (filename, "w")) == 0)
+ {
+ QSlog("Unable to open \"%s\" for output: %s.", filename,
+ strerror(errno));
+ }
+ }
+ ILL_CHECKnull (file, NULL);
+ rval = QSwrite_prob_EGioFile (p, file, filetype);
+ if (file)
+ {
+ EGioClose (file);
+ }
+CLEANUP:
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSwrite_prob_file (
+ EGLPNUM_TYPENAME_QSdata * p,
+ FILE * out,
+ const char *filetype)
+{
+ int rval = 0;
+ EGioFile_t*lout = EGioOpenFILE(out);
+ rval = QSwrite_prob_EGioFile(p,lout,filetype);
+ CHECKRVALG(rval,CLEANUP);
+ CLEANUP:
+ free(lout);
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSfree (
+ void *ptr)
+{
+ ILL_IFFREE (ptr, void);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSset_param (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int whichparam,
+ int newvalue)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ switch (whichparam)
+ {
+ case QS_PARAM_PRIMAL_PRICING:
+ if (newvalue == QS_PRICE_PDANTZIG ||
+ newvalue == QS_PRICE_PDEVEX ||
+ newvalue == QS_PRICE_PSTEEP || newvalue == QS_PRICE_PMULTPARTIAL)
+ {
+ p->pricing->pI_price = newvalue;
+ p->pricing->pII_price = newvalue;
+ }
+ else
+ {
+ QSlog("illegal value for QS_PARAM_PRIMAL_PRICING");
+ rval = 1;
+ goto CLEANUP;
+ }
+ break;
+ case QS_PARAM_DUAL_PRICING:
+ if (newvalue == QS_PRICE_DDANTZIG ||
+ newvalue == QS_PRICE_DSTEEP ||
+ newvalue == QS_PRICE_DMULTPARTIAL || newvalue == QS_PRICE_DDEVEX)
+ {
+ p->pricing->dI_price = newvalue;
+ p->pricing->dII_price = newvalue;
+ }
+ else
+ {
+ QSlog("illegal value for QS_PARAM_DUAL_PRICING");
+ rval = 1;
+ goto CLEANUP;
+ }
+ break;
+ case QS_PARAM_SIMPLEX_DISPLAY:
+ if (newvalue == 0 || (newvalue > 0 && newvalue < 4))
+ {
+ p->simplex_display = newvalue;
+ }
+ else
+ {
+ QSlog("illegal value for QS_PARAM_SIMPLEX_DISPLAY");
+ rval = 1;
+ goto CLEANUP;
+ }
+ break;
+ case QS_PARAM_SIMPLEX_MAX_ITERATIONS:
+ if (newvalue > 0)
+ {
+ p->lp->maxiter = newvalue;
+ }
+ else
+ {
+ QSlog("illegal value for QS_PARAM_SIMPLEX_MAX_ITERATIONS");
+ rval = 1;
+ goto CLEANUP;
+ }
+ break;
+ case QS_PARAM_SIMPLEX_SCALING:
+ if (newvalue == 0 || newvalue == 1)
+ {
+ p->simplex_scaling = newvalue;
+ }
+ else
+ {
+ QSlog("illegal value for QS_PARAM_SIMPLEX_SCALING");
+ rval = 1;
+ goto CLEANUP;
+ }
+ break;
+ default:
+ QSlog("unknown parameter: %d", whichparam);
+ rval = 1;
+ goto CLEANUP;
+ }
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSset_param_EGlpNum (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int whichparam,
+ EGLPNUM_TYPE newvalue)
+{
+ int rval = 0;
+ int sense;
+ EGLPNUM_TYPE lvar;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar(lvar);
+ EGLPNUM_TYPENAME_EGlpNumCopy(lvar,newvalue);
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ switch (whichparam)
+ {
+ case QS_PARAM_SIMPLEX_MAX_TIME:
+ if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (lvar))
+ {
+ p->lp->maxtime = EGLPNUM_TYPENAME_EGlpNumToLf (lvar);
+ }
+ else
+ {
+ QSlog("illegal value for QS_PARAM_SIMPLEX_MAX_TIME");
+ rval = 1;
+ goto CLEANUP;
+ }
+ break;
+ case QS_PARAM_OBJULIM:
+ EGLPNUM_TYPENAME_QSget_objsense(p,&sense);
+ if(EGLPNUM_TYPENAME_EGlpNumIsLeq(EGLPNUM_TYPENAME_ILL_MAXDOUBLE,lvar)) EGLPNUM_TYPENAME_EGlpNumCopy(lvar,EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+ EGLPNUM_TYPENAME_EGlpNumCopy(p->uobjlim,lvar);
+ if(sense == QS_MIN) EGLPNUM_TYPENAME_ILLsimplex_set_bound(p->lp,(const EGLPNUM_TYPE*)(&lvar), sense);
+ break;
+ case QS_PARAM_OBJLLIM:
+ EGLPNUM_TYPENAME_QSget_objsense(p,&sense);
+ if(EGLPNUM_TYPENAME_EGlpNumIsLeq(newvalue,EGLPNUM_TYPENAME_ILL_MINDOUBLE)) EGLPNUM_TYPENAME_EGlpNumCopy(lvar,EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+ EGLPNUM_TYPENAME_EGlpNumCopy(p->lobjlim,lvar);
+ if(sense == QS_MAX) EGLPNUM_TYPENAME_ILLsimplex_set_bound(p->lp,(const EGLPNUM_TYPE*)(&lvar), sense);
+ break;
+ default:
+ QSlog("unknown parameter: %d", whichparam);
+ rval = 1;
+ goto CLEANUP;
+ }
+
+CLEANUP:
+
+ EGLPNUM_TYPENAME_EGlpNumClearVar(lvar);
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_param (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int whichparam,
+ int *value)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (!value)
+ {
+ QSlog("EGLPNUM_TYPENAME_QSget_param call without a value pointer");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ switch (whichparam)
+ {
+ case QS_PARAM_PRIMAL_PRICING:
+ *value = p->pricing->pII_price;
+ break;
+ case QS_PARAM_DUAL_PRICING:
+ *value = p->pricing->dII_price;
+ break;
+ case QS_PARAM_SIMPLEX_DISPLAY:
+ *value = p->simplex_display;
+ break;
+ case QS_PARAM_SIMPLEX_MAX_ITERATIONS:
+ *value = p->lp->maxiter;
+ break;
+ case QS_PARAM_SIMPLEX_SCALING:
+ *value = p->simplex_scaling;
+ break;
+ default:
+ QSlog("unknown parameter: %d", whichparam);
+ rval = 1;
+ goto CLEANUP;
+ }
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSget_param_EGlpNum (
+ EGLPNUM_TYPENAME_QSdata * p,
+ int whichparam,
+ EGLPNUM_TYPE * value)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (p);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (!value)
+ {
+ QSlog("QSget_param_double call without a value pointer");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ switch (whichparam)
+ {
+ case QS_PARAM_SIMPLEX_MAX_TIME:
+ EGLPNUM_TYPENAME_EGlpNumSet (*value, p->lp->maxtime);
+ break;
+ case QS_PARAM_OBJULIM:
+ EGLPNUM_TYPENAME_EGlpNumCopy(*value,p->uobjlim);
+ break;
+ case QS_PARAM_OBJLLIM:
+ EGLPNUM_TYPENAME_EGlpNumCopy(*value,p->lobjlim);
+ break;
+ default:
+ QSlog("unknown parameter: %d", whichparam);
+ rval = 1;
+ goto CLEANUP;
+ }
+
+CLEANUP:
+
+ EG_RETURN (rval);
+}
+
+static int check_qsdata_pointer (
+ EGLPNUM_TYPENAME_QSdata * p)
+{
+ if (p == NULL)
+ {
+ QSlog("NULL EGLPNUM_TYPENAME_QSprob pointer");
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+static int formatIsMps (
+ const char *filetype,
+ int *isMps)
+{
+ int rval = 0;
+
+ if (!strcasecmp (filetype, "MPS"))
+ {
+ *isMps = 1;
+ }
+ else if (!strcasecmp (filetype, "LP"))
+ {
+ *isMps = 0;
+ }
+ else
+ {
+ QSlog("Unknown prob-file type: %s", filetype);
+ rval = 1;
+ ILL_CLEANUP;
+ }
+CLEANUP:
+ return rval;
+}
+
+
+/****************************************************************************/
+/*
+ * undocumentyed functions
+ */
+
+static void check_pointer (
+ void *p,
+ const char *fct,
+ const char *param)
+{
+ if (p == NULL)
+ QSlog("NULL %s argument to %s", param, fct);
+}
+
+/* EGLPNUM_TYPENAME_QSline_reader:
+ * used by mps/lp reader to get input lines
+ * by default input is read froma FILE* via fgets
+ */
+EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSline_reader EGLPNUM_TYPENAME_QSline_reader_new (
+ void *fct,
+ void *data_src)
+{
+ check_pointer (fct, "EGLPNUM_TYPENAME_QSline_reader_new", "fct");
+ check_pointer (data_src, "EGLPNUM_TYPENAME_QSline_reader_new", "data_src");
+ return EGLPNUM_TYPENAME_ILLline_reader_new ((EGLPNUM_TYPENAME_qsread_line_fct) fct, data_src);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSline_reader_set_error_collector (
+ EGLPNUM_TYPENAME_QSline_reader reader,
+ EGLPNUM_TYPENAME_QSerror_collector collector)
+{
+ check_pointer (reader, "EGLPNUM_TYPENAME_QSline_reader_set_error_collector", "reader");
+ check_pointer (collector, "EGLPNUM_TYPENAME_QSline_reader_set_error_collector", "collector");
+ reader->error_collector = collector;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSline_reader_free (
+ EGLPNUM_TYPENAME_QSline_reader reader)
+{
+ EGLPNUM_TYPENAME_ILLline_reader_free (reader);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE char *EGLPNUM_TYPENAME_QSline_reader_get (
+ EGLPNUM_TYPENAME_QSline_reader reader,
+ char *s,
+ int size)
+{
+ check_pointer (reader, "EGLPNUM_TYPENAME_QSline_reader_get", "reader");
+ check_pointer (s, "EGLPNUM_TYPENAME_QSline_reader_get", "s");
+ return EGLPNUM_TYPENAME_ILLline_reader_get (s, size, reader);
+}
+
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSerror_collector EGLPNUM_TYPENAME_QSerror_collector_new (
+ void *fct,
+ void *dest)
+{
+ check_pointer (fct, "EGLPNUM_TYPENAME_QSerror_collector_new", "fct");
+ return EGLPNUM_TYPENAME_ILLerror_collector_new ((EGLPNUM_TYPENAME_qsadd_error_fct) fct, dest);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE
+ EGLPNUM_TYPENAME_QSerror_collector EGLPNUM_TYPENAME_QSerror_memory_collector_new (EGLPNUM_TYPENAME_QSerror_memory mem)
+{
+ check_pointer (mem, "EGLPNUM_TYPENAME_QSerror_memory_collector_new", "mem");
+ return EGLPNUM_TYPENAME_ILLerror_memory_collector_new (mem);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSerror_collector_free (
+ EGLPNUM_TYPENAME_QSerror_collector c)
+{
+ EGLPNUM_TYPENAME_ILLerror_collector_free (c);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSdata *EGLPNUM_TYPENAME_QSget_prob (
+ EGLPNUM_TYPENAME_QSline_reader reader,
+ const char *probname,
+ const char *filetype)
+{
+ int isMps, rval = 0;
+ EGLPNUM_TYPENAME_QSdata *p = 0;
+
+ if ((filetype != NULL) && !strcasecmp (filetype, "MPS"))
+ {
+ isMps = 1;
+ }
+ else if ((filetype != NULL) && !strcasecmp (filetype, "LP"))
+ {
+ isMps = 0;
+ }
+ else
+ {
+ QSlog("Unknown prob-file type: %s",
+ (filetype != NULL) ? filetype : "NULL");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ p = EGLPNUM_TYPENAME_ILLread (reader, probname, isMps);
+ ILL_CHECKnull (p, NULL);
+
+ ILL_FAILfalse (p->qslp != NULL, "If there's a p there must be a p-qslp");
+ ILL_IFFREE (p->name, char);
+
+ ILL_UTIL_STR (p->name, p->qslp->probname);
+ EGLPNUM_TYPENAME_ILLsimplex_load_lpinfo (p->qslp, p->lp);
+
+CLEANUP:
+
+ if (rval != 0)
+ {
+ EGLPNUM_TYPENAME_QSfree_prob (p);
+ p = 0;
+ }
+ return p;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSreport_prob (
+ EGLPNUM_TYPENAME_QSdata * p,
+ const char *filetype,
+ EGLPNUM_TYPENAME_qserror_collector * c)
+{
+ int isMps, rval = 0;
+
+ rval = formatIsMps (filetype, &isMps);
+ CHECKRVALG (rval, CLEANUP);
+ if (isMps)
+ {
+ rval = EGLPNUM_TYPENAME_ILLwrite_mps (p->qslp, c);
+ }
+ else
+ {
+ rval = EGLPNUM_TYPENAME_ILLwrite_lp (p->qslp, c);
+ }
+CLEANUP:
+ EG_RETURN (rval);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE char *EGLPNUM_TYPENAME_QSversion (
+ void)
+{
+ char *name = 0;
+ name = EGsMalloc (char, 256);
+
+ snprintf (name, (size_t) 255, "%s (build %s-%s)",PACKAGE_STRING, __DATE__,
+ __TIME__);
+ return name;
+}
+
+/* QSstring_reporter:
+ * used by solver code to report feedback
+ * by default feedback is sent to logging
+ */
+EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSset_reporter (
+ EGLPNUM_TYPENAME_QSprob prob,
+ int skip,
+ void *fct,
+ void *dest)
+{
+ int rval = 0;
+
+ rval = check_qsdata_pointer (prob);
+ if (rval != 0)
+ return;
+
+ check_pointer (fct, "EGLPNUM_TYPENAME_QSset_reporter", "fct");
+
+ ILL_FAILtrue (prob->lp == NULL, "EGLPNUM_TYPENAME_QSprob internal error: prob->lp == NULL");
+ ILLstring_reporter_init (&prob->qslp->reporter,
+ (qsreport_string_fct) fct, dest);
+
+ prob->lp->iterskip = skip;
+CLEANUP:
+ return;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE const char *EGLPNUM_TYPENAME_QSformat_error_type_string (
+ int tp)
+{
+ const char *type = "Error";
+
+ if (tp == QS_DATA_ERROR)
+ {
+ type = "Data Error";
+ }
+ if (tp == QS_DATA_WARN)
+ {
+ type = "Data Warning";
+ }
+ if (tp == QS_MPS_FORMAT_ERROR)
+ {
+ type = "MPS Error";
+ }
+ if (tp == QS_MPS_FORMAT_WARN)
+ {
+ type = "MPS Warning";
+ }
+ if (tp == QS_LP_FORMAT_ERROR)
+ {
+ type = "LP Error";
+ }
+ if (tp == QS_LP_FORMAT_WARN)
+ {
+ type = "LP Warning";
+ }
+ return type;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSerror_get_type (
+ EGLPNUM_TYPENAME_QSformat_error error)
+{
+ check_pointer (error, "EGLPNUM_TYPENAME_QSerror_get_type", "error");
+ return error->type;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE const char *EGLPNUM_TYPENAME_QSerror_get_desc (
+ EGLPNUM_TYPENAME_QSformat_error error)
+{
+ check_pointer (error, "EGLPNUM_TYPENAME_QSerror_get_desc", "error");
+ return error->desc;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSerror_get_line_number (
+ EGLPNUM_TYPENAME_QSformat_error error)
+{
+ check_pointer (error, "EGLPNUM_TYPENAME_QSerror_get_line_number", "error");
+ return error->lineNumber;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSerror_get_pos (
+ EGLPNUM_TYPENAME_QSformat_error error)
+{
+ check_pointer (error, "EGLPNUM_TYPENAME_QSerror_get_pos", "error");
+ return error->at;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE const char *EGLPNUM_TYPENAME_QSerror_get_line (
+ EGLPNUM_TYPENAME_QSformat_error error)
+{
+ check_pointer (error, "EGLPNUM_TYPENAME_QSerror_get_line", "error");
+ return error->theLine;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSerror_print (
+ FILE * f,
+ EGLPNUM_TYPENAME_QSformat_error error)
+{
+ check_pointer (f, "EGLPNUM_TYPENAME_QSerror_print", "f");
+ if (error == NULL)
+ {
+ QSlog("0");
+ }
+ else
+ {
+ EGioFile_t*out = EGioOpenFILE(f);
+ EGLPNUM_TYPENAME_ILLformat_error_print (out, error);
+ EGioClose(out);
+ }
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSerror_memory EGLPNUM_TYPENAME_QSerror_memory_create (
+ int takeErrorLines)
+{
+ return EGLPNUM_TYPENAME_ILLerror_memory_create (takeErrorLines);
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSerror_memory_free (
+ EGLPNUM_TYPENAME_QSerror_memory mem)
+{
+ if (mem != NULL)
+ {
+ EGLPNUM_TYPENAME_ILLerror_memory_free (mem);
+ }
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSerror_memory_get_nerrors (
+ EGLPNUM_TYPENAME_QSerror_memory mem)
+{
+ check_pointer (mem, "EGLPNUM_TYPENAME_QSerror_memory_get_nerrors", "mem");
+ return mem->nerror;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSerror_memory_get_nof (
+ EGLPNUM_TYPENAME_QSerror_memory mem,
+ int type)
+{
+ check_pointer (mem, "EGLPNUM_TYPENAME_QSerror_memory_get_nerrors", "mem");
+ if (0 <= type && type < QS_INPUT_NERROR)
+ {
+ return mem->has_error[type];
+ }
+ else
+ {
+ ILL_REPRT ("bad error type");
+ return 0;
+ }
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSformat_error EGLPNUM_TYPENAME_QSerror_memory_get_last_error (
+ EGLPNUM_TYPENAME_QSerror_memory mem)
+{
+ check_pointer (mem, "QSerror_memory_get_last_errors", "mem");
+ return mem->error_list;
+}
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSformat_error EGLPNUM_TYPENAME_QSerror_memory_get_prev_error (
+ EGLPNUM_TYPENAME_QSformat_error e)
+{
+ check_pointer (e, "QSerror_memory_get_prev_errors", "e");
+ if (e != NULL)
+ e = e->next;
+ return e;
+}
diff --git a/qsopt_ex/qsopt.h b/qsopt_ex/qsopt.h
new file mode 100644
index 0000000..bd4ec7b
--- /dev/null
+++ b/qsopt_ex/qsopt.h
@@ -0,0 +1,358 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* $RCSfile: qsopt_EGLPNUM_TYPENAME.h,v $ $Revision: 1.3 $ $Date: 2003/11/05 16:57:39 $" */
+#ifndef EGLPNUM_TYPENAME___QS_QSOPT_H
+#define EGLPNUM_TYPENAME___QS_QSOPT_H
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <gmp.h>
+
+#ifdef WIN32
+
+#ifdef QSLIB_EXPORTS
+#define EGLPNUM_TYPENAME_QSLIB_INTERFACE __declspec(dllexport)
+#else
+#define EGLPNUM_TYPENAME_QSLIB_INTERFACE __declspec(dllimport)
+#endif
+
+#else
+#define EGLPNUM_TYPENAME_QSLIB_INTERFACE extern
+#endif
+
+#ifdef WIN32
+typedef struct EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_qsdata *EGLPNUM_TYPENAME_QSprob;
+typedef struct EGLPNUM_TYPENAME_QSLIB_INTERFACE qsbasis *EGLPNUM_TYPENAME_QSbas;
+#else
+typedef struct EGLPNUM_TYPENAME_qsdata *EGLPNUM_TYPENAME_QSprob;
+typedef struct qsbasis *EGLPNUM_TYPENAME_QSbas;
+#endif
+
+/****************************************************************************/
+/* */
+/* PARAMETERS TO SPECIFY OBJECTIVE SENSE */
+/* */
+/****************************************************************************/
+#include "basicdefs.h"
+/*
+#define QS_LP_PRIMAL_FEASIBLE 11
+#define QS_LP_PRIMAL_INFEASIBLE 12
+#define QS_LP_PRIMAL_UNBOUNDED 13
+#define QS_LP_DUAL_FEASIBLE 14
+#define QS_LP_DUAL_INFEASIBLE 15
+#define QS_LP_DUAL_UNBOUNDED 16
+*/
+
+/****************************************************************************/
+/* */
+/* QSopt Library Functions */
+/* */
+/****************************************************************************/
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#ifdef WIN32
+/*
+ * in WINDOWS we make
+ * EGLPNUM_TYPENAME_solver_main/EGLPNUM_TYPENAME_reader_main part of DLL
+ */
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_solver_main ( int argc, char **argv);
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_reader_main ( int argc, char **argv);
+#endif
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSfree ( void *ptr),
+ EGLPNUM_TYPENAME_QSfree_prob ( EGLPNUM_TYPENAME_QSprob p),
+ EGLPNUM_TYPENAME_QSfree_basis ( EGLPNUM_TYPENAME_QSbas B),
+ EGLPNUM_TYPENAME_QSset_precision ( const unsigned prec),/**< set the precision for floating
+ point numbers to the given
+ number of bits */
+ EGLPNUM_TYPENAME_QSstart ( void),/**< whe we use non native numbers, we need to make
+ some initializations before operating with the
+ library */
+ EGLPNUM_TYPENAME_QSend ( void); /**< just to free any internal static data needed by
+ the variable precision numbers */
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSopt_primal ( EGLPNUM_TYPENAME_QSprob p, int *status),
+ EGLPNUM_TYPENAME_QSopt_dual ( EGLPNUM_TYPENAME_QSprob p, int *status),
+ EGLPNUM_TYPENAME_QSopt_pivotin_col ( EGLPNUM_TYPENAME_QSprob p, int ccnt, int *clist),
+ EGLPNUM_TYPENAME_QSopt_pivotin_row ( EGLPNUM_TYPENAME_QSprob p, int rcnt, int *rlist),
+ EGLPNUM_TYPENAME_QSopt_strongbranch ( EGLPNUM_TYPENAME_QSprob p, int ncand, int *candidatelist,
+ EGLPNUM_TYPE * xlist, EGLPNUM_TYPE * down_vals, EGLPNUM_TYPE * up_vals,
+ int iterations, EGLPNUM_TYPE objbound),
+ EGLPNUM_TYPENAME_QSchange_objsense ( EGLPNUM_TYPENAME_QSprob p, int newsense),
+ EGLPNUM_TYPENAME_QSget_objsense ( EGLPNUM_TYPENAME_QSprob p, int *newsense),
+ EGLPNUM_TYPENAME_QSnew_col ( EGLPNUM_TYPENAME_QSprob p,const EGLPNUM_TYPE obj,const EGLPNUM_TYPE lower,const EGLPNUM_TYPE upper,
+ const char *name),
+ EGLPNUM_TYPENAME_QSadd_cols ( EGLPNUM_TYPENAME_QSprob p, int num, int *cmatcnt, int *cmatbeg, int *cmatind,
+ EGLPNUM_TYPE * cmatval, EGLPNUM_TYPE * obj, EGLPNUM_TYPE * lower,
+ EGLPNUM_TYPE * upper, const char **names),
+ EGLPNUM_TYPENAME_QSadd_col ( EGLPNUM_TYPENAME_QSprob p, int cnt, int *cmatind, EGLPNUM_TYPE * cmatval,
+ EGLPNUM_TYPE obj, EGLPNUM_TYPE lower, EGLPNUM_TYPE upper, const char *name),
+ EGLPNUM_TYPENAME_QSnew_row ( EGLPNUM_TYPENAME_QSprob p,const EGLPNUM_TYPE rhs, int sense, const char *name),
+ EGLPNUM_TYPENAME_QSadd_ranged_rows ( EGLPNUM_TYPENAME_QSprob p, int num, int *rmatcnt, int *rmatbeg,
+ int *rmatind,const EGLPNUM_TYPE * rmatval,const EGLPNUM_TYPE * rhs, char *sense,
+ const EGLPNUM_TYPE* range, const char **names),
+ EGLPNUM_TYPENAME_QSadd_ranged_row ( EGLPNUM_TYPENAME_QSprob p, int cnt, int *rmatind,const EGLPNUM_TYPE * rmatval,
+ const EGLPNUM_TYPE * rhs, int sense,const EGLPNUM_TYPE * range, const char *name),
+ EGLPNUM_TYPENAME_QSadd_rows ( EGLPNUM_TYPENAME_QSprob p, int num, int *rmatcnt, int *rmatbeg, int *rmatind,
+ const EGLPNUM_TYPE * rmatval,const EGLPNUM_TYPE * rhs, char *sense, const char **names),
+ EGLPNUM_TYPENAME_QSadd_row ( EGLPNUM_TYPENAME_QSprob p, int cnt, int *rmatind,const EGLPNUM_TYPE * rmatval,
+ const EGLPNUM_TYPE * rhs, int sense, const char *name),
+ EGLPNUM_TYPENAME_QSdelete_rows ( EGLPNUM_TYPENAME_QSprob p, int num, int *dellist),
+ EGLPNUM_TYPENAME_QSdelete_row ( EGLPNUM_TYPENAME_QSprob p, int rowindex),
+ EGLPNUM_TYPENAME_QSdelete_setrows ( EGLPNUM_TYPENAME_QSprob p, int *flags),
+ EGLPNUM_TYPENAME_QSdelete_named_row ( EGLPNUM_TYPENAME_QSprob p, const char *rowname),
+ EGLPNUM_TYPENAME_QSdelete_named_rows_list ( EGLPNUM_TYPENAME_QSprob p, int num, const char **rownames),
+ EGLPNUM_TYPENAME_QSdelete_cols ( EGLPNUM_TYPENAME_QSprob p, int num, int *dellist),
+ EGLPNUM_TYPENAME_QSdelete_col ( EGLPNUM_TYPENAME_QSprob p, int colindex),
+ EGLPNUM_TYPENAME_QSdelete_setcols ( EGLPNUM_TYPENAME_QSprob p, int *flags),
+ EGLPNUM_TYPENAME_QSdelete_named_column ( EGLPNUM_TYPENAME_QSprob p, const char *colname),
+ EGLPNUM_TYPENAME_QSdelete_named_columns_list ( EGLPNUM_TYPENAME_QSprob p, int num, const char **colnames),
+ EGLPNUM_TYPENAME_QSchange_senses ( EGLPNUM_TYPENAME_QSprob p, int num, int *rowlist, char *sense),
+ EGLPNUM_TYPENAME_QSchange_sense ( EGLPNUM_TYPENAME_QSprob p, int rowindex, int sense),
+ EGLPNUM_TYPENAME_QSchange_coef ( EGLPNUM_TYPENAME_QSprob p, int rowindex, int colindex, EGLPNUM_TYPE coef),
+ EGLPNUM_TYPENAME_QSchange_objcoef ( EGLPNUM_TYPENAME_QSprob p, int indx, EGLPNUM_TYPE coef),
+ EGLPNUM_TYPENAME_QSchange_rhscoef ( EGLPNUM_TYPENAME_QSprob p, int indx, EGLPNUM_TYPE coef),
+ EGLPNUM_TYPENAME_QSchange_range(EGLPNUM_TYPENAME_QSprob p, int rowindex, EGLPNUM_TYPE range),
+ EGLPNUM_TYPENAME_QSchange_bounds ( EGLPNUM_TYPENAME_QSprob p, int num, int *collist, char *lu,
+ const EGLPNUM_TYPE * bounds),
+ EGLPNUM_TYPENAME_QSchange_bound ( EGLPNUM_TYPENAME_QSprob p, int indx, int lu,const EGLPNUM_TYPE bound),
+ EGLPNUM_TYPENAME_QSload_basis ( EGLPNUM_TYPENAME_QSprob p, EGLPNUM_TYPENAME_QSbas B),
+ EGLPNUM_TYPENAME_QSread_and_load_basis ( EGLPNUM_TYPENAME_QSprob p, const char *filename),
+ EGLPNUM_TYPENAME_QSload_basis_array ( EGLPNUM_TYPENAME_QSprob p, char *cstat, char *rstat),
+ EGLPNUM_TYPENAME_QSload_basis_and_row_norms_array ( EGLPNUM_TYPENAME_QSprob p, char *cstat, char *rstat,
+ EGLPNUM_TYPE * rownorms),
+ EGLPNUM_TYPENAME_QSget_basis_array ( EGLPNUM_TYPENAME_QSprob p, char *cstat, char *rstat),
+ EGLPNUM_TYPENAME_QSget_basis_and_row_norms_array ( EGLPNUM_TYPENAME_QSprob p, char *cstat, char *rstat,
+ EGLPNUM_TYPE * rownorms),
+ EGLPNUM_TYPENAME_QSget_binv_row ( EGLPNUM_TYPENAME_QSprob p, int indx, EGLPNUM_TYPE * binvrow),
+ EGLPNUM_TYPENAME_QSget_tableau_row ( EGLPNUM_TYPENAME_QSprob p, int indx, EGLPNUM_TYPE * tableaurow),
+ EGLPNUM_TYPENAME_QSget_basis_order ( EGLPNUM_TYPENAME_QSprob p, int *basorder),
+ EGLPNUM_TYPENAME_QSget_coef (EGLPNUM_TYPENAME_QSprob p, int rowindex, int colindex, EGLPNUM_TYPE*coef),
+ EGLPNUM_TYPENAME_QSget_status ( EGLPNUM_TYPENAME_QSprob p, int *status),
+ EGLPNUM_TYPENAME_QSget_solution ( EGLPNUM_TYPENAME_QSprob p, EGLPNUM_TYPE * value, EGLPNUM_TYPE * x,
+ EGLPNUM_TYPE * pi, EGLPNUM_TYPE * slack, EGLPNUM_TYPE * rc),
+ EGLPNUM_TYPENAME_QSget_objval ( EGLPNUM_TYPENAME_QSprob p, EGLPNUM_TYPE * value),
+ EGLPNUM_TYPENAME_QSget_pi_array ( EGLPNUM_TYPENAME_QSprob p, EGLPNUM_TYPE * pi),
+ EGLPNUM_TYPENAME_QSget_rc_array ( EGLPNUM_TYPENAME_QSprob p, EGLPNUM_TYPE * rc),
+ EGLPNUM_TYPENAME_QSget_x_array ( EGLPNUM_TYPENAME_QSprob p, EGLPNUM_TYPE * x),
+ EGLPNUM_TYPENAME_QSget_slack_array ( EGLPNUM_TYPENAME_QSprob p, EGLPNUM_TYPE * slack),
+ EGLPNUM_TYPENAME_QSget_infeas_array ( EGLPNUM_TYPENAME_QSprob p, EGLPNUM_TYPE * pi),
+ EGLPNUM_TYPENAME_QSget_colcount ( EGLPNUM_TYPENAME_QSprob p),
+ EGLPNUM_TYPENAME_QSget_rowcount ( EGLPNUM_TYPENAME_QSprob p),
+ EGLPNUM_TYPENAME_QSget_nzcount ( EGLPNUM_TYPENAME_QSprob p),
+ EGLPNUM_TYPENAME_QSget_obj_list(EGLPNUM_TYPENAME_QSprob p, int num, int*collist, EGLPNUM_TYPE*obj),
+ EGLPNUM_TYPENAME_QSget_obj ( EGLPNUM_TYPENAME_QSprob p, EGLPNUM_TYPE * obj),
+ EGLPNUM_TYPENAME_QSget_rhs ( EGLPNUM_TYPENAME_QSprob p, EGLPNUM_TYPE * rhs),
+ EGLPNUM_TYPENAME_QSget_ranged_rows_list ( EGLPNUM_TYPENAME_QSprob p, int num, int *rowlist, int **rowcnt,
+ int **rowbeg, int **rowind, EGLPNUM_TYPE ** rowval, EGLPNUM_TYPE ** rhs,
+ char **sense, EGLPNUM_TYPE **range, char ***names),
+ EGLPNUM_TYPENAME_QSget_ranged_rows ( EGLPNUM_TYPENAME_QSprob p, int **rowcnt, int **rowbeg, int **rowind,
+ EGLPNUM_TYPE ** rowval, EGLPNUM_TYPE ** rhs, char **sense,
+ EGLPNUM_TYPE ** range, char ***names),
+ EGLPNUM_TYPENAME_QSget_senses ( EGLPNUM_TYPENAME_QSprob p, char*senses),
+ EGLPNUM_TYPENAME_QSget_rows_list ( EGLPNUM_TYPENAME_QSprob p, int num, int *rowlist, int **rowcnt,
+ int **rowbeg, int **rowind, EGLPNUM_TYPE ** rowval, EGLPNUM_TYPE ** rhs,
+ char **sense, char ***names),
+ EGLPNUM_TYPENAME_QSget_rows ( EGLPNUM_TYPENAME_QSprob p, int **rowcnt, int **rowbeg, int **rowind,
+ EGLPNUM_TYPE ** rowval, EGLPNUM_TYPE ** rhs, char **sense, char ***names),
+ EGLPNUM_TYPENAME_QSget_columns_list ( EGLPNUM_TYPENAME_QSprob p, int num, int *collist, int **colcnt,
+ int **colbeg, int **colind, EGLPNUM_TYPE ** colval, EGLPNUM_TYPE ** obj,
+ EGLPNUM_TYPE ** lower, EGLPNUM_TYPE ** upper, char ***names),
+ EGLPNUM_TYPENAME_QSget_columns ( EGLPNUM_TYPENAME_QSprob p, int **colcnt, int **colbeg, int **colind,
+ EGLPNUM_TYPE ** colval, EGLPNUM_TYPE ** obj, EGLPNUM_TYPE ** lower,
+ EGLPNUM_TYPE ** upper, char ***names),
+ EGLPNUM_TYPENAME_QSget_rownames ( EGLPNUM_TYPENAME_QSprob p, char **rownames),
+ EGLPNUM_TYPENAME_QSget_colnames ( EGLPNUM_TYPENAME_QSprob p, char **colnames),
+ EGLPNUM_TYPENAME_QSget_bound ( EGLPNUM_TYPENAME_QSprob p, int colindex, int lu, EGLPNUM_TYPE * bound),
+ EGLPNUM_TYPENAME_QSget_bounds ( EGLPNUM_TYPENAME_QSprob p, EGLPNUM_TYPE * lower, EGLPNUM_TYPE * upper),
+ EGLPNUM_TYPENAME_QSget_bounds_list(EGLPNUM_TYPENAME_QSprob p, int num, int*collist, EGLPNUM_TYPE*lb,
+ EGLPNUM_TYPE*ub),
+ EGLPNUM_TYPENAME_QSget_intflags ( EGLPNUM_TYPENAME_QSprob p, int *intflags),
+ EGLPNUM_TYPENAME_QSget_intcount ( EGLPNUM_TYPENAME_QSprob p, int *count),
+ EGLPNUM_TYPENAME_QSget_column_index ( EGLPNUM_TYPENAME_QSprob p, const char *name, int *colindex),
+ EGLPNUM_TYPENAME_QSget_row_index ( EGLPNUM_TYPENAME_QSprob p, const char *name, int *rowindex),
+ EGLPNUM_TYPENAME_QSget_named_x ( EGLPNUM_TYPENAME_QSprob p, const char *colname, EGLPNUM_TYPE * val),
+ EGLPNUM_TYPENAME_QSget_named_rc ( EGLPNUM_TYPENAME_QSprob p, const char *colname, EGLPNUM_TYPE * val),
+ EGLPNUM_TYPENAME_QSget_named_pi ( EGLPNUM_TYPENAME_QSprob p, const char *rowname, EGLPNUM_TYPE * val),
+ EGLPNUM_TYPENAME_QSget_named_slack ( EGLPNUM_TYPENAME_QSprob p, const char *rowname, EGLPNUM_TYPE * val),
+ EGLPNUM_TYPENAME_QScompute_row_norms ( EGLPNUM_TYPENAME_QSprob p),
+ EGLPNUM_TYPENAME_QSwrite_prob ( EGLPNUM_TYPENAME_QSprob p, const char *filename, const char *filetype),
+ EGLPNUM_TYPENAME_QSwrite_prob_file ( EGLPNUM_TYPENAME_QSprob p, FILE * file, const char *filetype),
+ EGLPNUM_TYPENAME_QSwrite_basis ( EGLPNUM_TYPENAME_QSprob p, EGLPNUM_TYPENAME_QSbas B, const char *filename),
+ EGLPNUM_TYPENAME_QStest_row_norms ( EGLPNUM_TYPENAME_QSprob p),
+ EGLPNUM_TYPENAME_QSget_itcnt(EGLPNUM_TYPENAME_QSprob p, int *pI_iter, int *pII_iter, int *dI_iter,
+ int *dII_iter, int *tot_iter),
+ EGLPNUM_TYPENAME_QSset_param ( EGLPNUM_TYPENAME_QSprob p, int whichparam, int newvalue),
+ EGLPNUM_TYPENAME_QSset_param_EGlpNum ( EGLPNUM_TYPENAME_QSprob p, int whichparam, EGLPNUM_TYPE newvalue),
+ EGLPNUM_TYPENAME_QSget_param ( EGLPNUM_TYPENAME_QSprob p, int whichparam, int *value),
+ EGLPNUM_TYPENAME_QSget_param_EGlpNum ( EGLPNUM_TYPENAME_QSprob p, int whichparam, EGLPNUM_TYPE * value);
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE char *EGLPNUM_TYPENAME_QSget_probname ( EGLPNUM_TYPENAME_QSprob p);
+EGLPNUM_TYPENAME_QSLIB_INTERFACE char *EGLPNUM_TYPENAME_QSget_objname ( EGLPNUM_TYPENAME_QSprob p);
+EGLPNUM_TYPENAME_QSLIB_INTERFACE char *EGLPNUM_TYPENAME_QSversion ( void);
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSprob EGLPNUM_TYPENAME_QScreate_prob ( const char *name, int objsense),
+ EGLPNUM_TYPENAME_QSread_prob ( const char *filename, const char *filetype),
+ EGLPNUM_TYPENAME_QSload_prob ( const char *probname, int ncols, int nrows, int *cmatcnt,
+ int *cmatbeg, int *cmatind, EGLPNUM_TYPE * cmatval, int objsense,
+ EGLPNUM_TYPE * obj, EGLPNUM_TYPE * rhs, char *sense, EGLPNUM_TYPE * lower,
+ EGLPNUM_TYPE * upper, const char **colnames, const char **rownames),
+ EGLPNUM_TYPENAME_QScopy_prob ( EGLPNUM_TYPENAME_QSprob p, const char *newname);
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSbas EGLPNUM_TYPENAME_QSget_basis ( EGLPNUM_TYPENAME_QSprob p),
+ EGLPNUM_TYPENAME_QSread_basis ( EGLPNUM_TYPENAME_QSprob p, const char *filename);
+
+#ifdef __cplusplus
+}
+#endif
+
+/****************************************************************************
+ *
+ * This is the undocumented part of the QSlib interface
+ *
+ ****************************************************************************/
+/*
+ * functions to facilitate line by line reading from other sources than
+ * files from within MPS/LP parsers
+ *
+ * functions to facilitate the collection of error information instead of
+ * having the parsers print messages to stderr
+ * by mps/lp format writers
+ *
+ * a problem's reporter is used by the solver code to provide important
+ * feedback/progress information
+ */
+
+#ifdef WIN32
+typedef struct EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_qsline_reader *EGLPNUM_TYPENAME_QSline_reader;
+typedef struct EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_qsformat_error *EGLPNUM_TYPENAME_QSformat_error;
+typedef struct EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_qserror_collector *EGLPNUM_TYPENAME_QSerror_collector;
+typedef struct EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_qserror_memory *EGLPNUM_TYPENAME_QSerror_memory;
+#else
+typedef struct EGLPNUM_TYPENAME_qsline_reader *EGLPNUM_TYPENAME_QSline_reader;
+typedef struct EGLPNUM_TYPENAME_qsformat_error *EGLPNUM_TYPENAME_QSformat_error;
+typedef struct EGLPNUM_TYPENAME_qserror_collector *EGLPNUM_TYPENAME_QSerror_collector;
+typedef struct EGLPNUM_TYPENAME_qserror_memory *EGLPNUM_TYPENAME_QSerror_memory;
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSgrab_cache (EGLPNUM_TYPENAME_QSprob p, int status);
+
+ EGLPNUM_TYPENAME_QSLIB_INTERFACE const char *EGLPNUM_TYPENAME_QSformat_error_type_string (
+ int tp);
+
+ EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSerror_get_type (
+ EGLPNUM_TYPENAME_QSformat_error error);
+ EGLPNUM_TYPENAME_QSLIB_INTERFACE const char *EGLPNUM_TYPENAME_QSerror_get_desc (
+ EGLPNUM_TYPENAME_QSformat_error error);
+ EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSerror_get_line_number (
+ EGLPNUM_TYPENAME_QSformat_error error);
+ EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSerror_get_pos (
+ EGLPNUM_TYPENAME_QSformat_error error);
+ EGLPNUM_TYPENAME_QSLIB_INTERFACE const char *EGLPNUM_TYPENAME_QSerror_get_line (
+ EGLPNUM_TYPENAME_QSformat_error error);
+ EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSerror_print (
+ FILE * f,
+ EGLPNUM_TYPENAME_QSformat_error error);
+
+ EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSerror_collector EGLPNUM_TYPENAME_QSerror_collector_new (
+ void *fct,
+ void *dest);
+ EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSerror_collector EGLPNUM_TYPENAME_QSerror_memory_collector_new (
+ EGLPNUM_TYPENAME_QSerror_memory mem);
+ EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSerror_collector_free (
+ EGLPNUM_TYPENAME_QSerror_collector c);
+
+/****************************************************************************
+ * line reader
+ */
+ EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSline_reader EGLPNUM_TYPENAME_QSline_reader_new (
+ void *fct,
+ void *data_src);
+ /* reader->read_line_fct defaults to fgets */
+
+ EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSline_reader_free (
+ EGLPNUM_TYPENAME_QSline_reader reader);
+
+ EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSline_reader_set_error_collector (
+ EGLPNUM_TYPENAME_QSline_reader reader,
+ EGLPNUM_TYPENAME_QSerror_collector collector);
+
+ EGLPNUM_TYPENAME_QSLIB_INTERFACE char *EGLPNUM_TYPENAME_QSline_reader_get (
+ EGLPNUM_TYPENAME_QSline_reader reader,
+ char *s,
+ int size);
+
+ EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSprob EGLPNUM_TYPENAME_QSget_prob (
+ EGLPNUM_TYPENAME_QSline_reader reader,
+ const char *probname,
+ const char *filetype);
+ /* the MPS and LP parsers uses the fct from reader
+ * to get to next input line */
+
+
+/****************************************************************************
+ * error memory
+ */
+ EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSerror_memory EGLPNUM_TYPENAME_QSerror_memory_create (
+ int takeErrorLines);
+ EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSerror_memory_free (
+ EGLPNUM_TYPENAME_QSerror_memory mem);
+
+ EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSerror_memory_get_nof (
+ EGLPNUM_TYPENAME_QSerror_memory mem,
+ int error_type);
+ EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSerror_memory_get_nerrors (
+ EGLPNUM_TYPENAME_QSerror_memory mem);
+
+ EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSformat_error EGLPNUM_TYPENAME_QSerror_memory_get_last_error (
+ EGLPNUM_TYPENAME_QSerror_memory mem);
+ EGLPNUM_TYPENAME_QSLIB_INTERFACE EGLPNUM_TYPENAME_QSformat_error EGLPNUM_TYPENAME_QSerror_memory_get_prev_error (
+ EGLPNUM_TYPENAME_QSformat_error e);
+
+/****************************************************************************
+ * reporter for solver feedback
+ */
+ EGLPNUM_TYPENAME_QSLIB_INTERFACE void EGLPNUM_TYPENAME_QSset_reporter (
+ EGLPNUM_TYPENAME_QSprob prob,
+ int iterskip,
+ void *fct,
+ void *dest);
+
+ EGLPNUM_TYPENAME_QSLIB_INTERFACE int EGLPNUM_TYPENAME_QSreport_prob (
+ EGLPNUM_TYPENAME_QSprob p,
+ const char *filetype,
+ EGLPNUM_TYPENAME_QSerror_collector c);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* EGLPNUM_TYPENAME___QS_QSOPT_H */
diff --git a/qsopt_ex/qstruct.h b/qsopt_ex/qstruct.h
new file mode 100644
index 0000000..21e83b7
--- /dev/null
+++ b/qsopt_ex/qstruct.h
@@ -0,0 +1,49 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* $RCSfile: qstruct_EGLPNUM_TYPENAME.h,v $ $Revision: 1.3 $ $Date: 2003/11/05 16:57:39 $" */
+#ifndef EGLPNUM_TYPENAME___QS_QSTRUCT_H
+#define EGLPNUM_TYPENAME___QS_QSTRUCT_H
+
+#include "basicdefs.h"
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+#include "eg_lpnum.h"
+
+typedef struct EGLPNUM_TYPENAME_qsdata
+{
+ struct EGLPNUM_TYPENAME_ILLlpdata *qslp;
+ struct EGLPNUM_TYPENAME_lpinfo *lp;
+ struct EGLPNUM_TYPENAME_price_info *pricing;
+ struct EGLPNUM_TYPENAME_ILLlp_basis *basis;
+ struct EGLPNUM_TYPENAME_ILLlp_cache *cache;
+ char *name;
+ int qstatus; /* QS_LP_UNSOLVED or an opt status */
+ int factorok; /* set to 0 if factorization is old */
+ int simplex_display; /* 0 off, 1 on */
+ int simplex_scaling; /* 0 off, 1 on */
+ itcnt_t itcnt;
+ EGLPNUM_TYPE uobjlim;
+ EGLPNUM_TYPE lobjlim;
+}
+EGLPNUM_TYPENAME_QSdata;
+
+#endif /* EGLPNUM_TYPENAME___QS_QSTRUCT_H */
diff --git a/qsopt_ex/ratio.c b/qsopt_ex/ratio.c
new file mode 100644
index 0000000..5463cca
--- /dev/null
+++ b/qsopt_ex/ratio.c
@@ -0,0 +1,1297 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* "$RCSfile: ratio.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+static int TRACE = 0;
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "logging-private.h"
+
+#include "eg_lpnum.h"
+#include "eg_io.h"
+#include "except.h"
+#include "trace.h"
+
+#include "sortrus_EGLPNUM_TYPENAME.h"
+#include "stddefs.h"
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+#include "ratio_EGLPNUM_TYPENAME.h"
+#include "fct_EGLPNUM_TYPENAME.h"
+
+
+void EGLPNUM_TYPENAME_ILLratio_pI_test (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int eindex,
+ int dir,
+ EGLPNUM_TYPENAME_ratio_res * rs)
+{
+ int i = 0, k = 0;
+ int col, ecol;
+ int cbnd, indx = 0;
+ int tctr = 0;
+ int *perm = lp->upd.perm;
+ int *ix = lp->upd.ix;
+ EGLPNUM_TYPE *pivtol = &(lp->tol->pivot_tol);
+ EGLPNUM_TYPE *dftol = &(lp->tol->id_tol);
+
+ /*HHH*/ EGLPNUM_TYPE * t = lp->upd.t;
+ EGLPNUM_TYPE t_i, delta, y_ij, rcost, nrcost, ntmp;
+ EGLPNUM_TYPE *x, *l, *u;
+
+ /*HHH*/ EGLPNUM_TYPENAME_EGlpNumInitVar (t_i);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (delta);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (y_ij);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (rcost);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (nrcost);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (ntmp);
+ EGLPNUM_TYPENAME_EGlpNumZero (t_i);
+ EGLPNUM_TYPENAME_EGlpNumZero (y_ij);
+ EGLPNUM_TYPENAME_EGlpNumZero (delta);
+ rs->lindex = -1;
+ EGLPNUM_TYPENAME_EGlpNumZero (rs->tz);
+ EGLPNUM_TYPENAME_EGlpNumZero (rs->pivotval);
+ rs->ratio_stat = RATIO_FAILED;
+ rs->lvstat = -1;
+ ecol = lp->nbaz[eindex];
+ ILL_IFTRACE2 ("%s:%d:%d:%d:%d", __func__, eindex, dir, ecol,
+ (VBOUNDED == lp->vtype[ecol]));
+ if (lp->vtype[ecol] == VBOUNDED)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (t[0], lp->uz[ecol], lp->lz[ecol]);
+ ix[0] = BBOUND;
+ ILL_IFTRACE2 (":%d[%d](%la,%la,%la)\n", ix[tctr], tctr,
+ EGLPNUM_TYPENAME_EGlpNumToLf (t[tctr]), EGLPNUM_TYPENAME_EGlpNumToLf (lp->uz[ecol]),
+ EGLPNUM_TYPENAME_EGlpNumToLf (lp->lz[ecol]));
+ tctr++;
+ }
+ ILL_IFTRACE2 (":%d", lp->yjz.nzcnt);
+ for (k = 0; k < lp->yjz.nzcnt; k++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (y_ij, lp->yjz.coef[k]);
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (y_ij, *pivtol))
+ continue;
+
+ i = lp->yjz.indx[k];
+ x = &(lp->xbz[i]);
+ col = lp->baz[i];
+ l = &(lp->lz[col]);
+ u = &(lp->uz[col]);
+
+ if ((dir == VINCREASE && EGLPNUM_TYPENAME_EGlpNumIsGreatZero (y_ij)) ||
+ (dir == VDECREASE && EGLPNUM_TYPENAME_EGlpNumIsLessZero (y_ij)))
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (y_ij))
+ EGLPNUM_TYPENAME_EGlpNumSign (y_ij);
+ ILL_IFTRACE2 (":%d", lp->bfeas[i]);
+ if (lp->bfeas[i] > 0)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (t[tctr], *x, *u, y_ij);
+ ix[tctr] = 10 * k + BATOUPPER;
+ ILL_IFTRACE2 (":%d[%d](%la)\n", ix[tctr], tctr, EGLPNUM_TYPENAME_EGlpNumToLf (t[tctr]));
+ tctr++;
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*l, EGLPNUM_TYPENAME_NINFTY))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (t[tctr], *x, *l, y_ij);
+ ix[tctr] = 10 * k + BATOLOWER;
+ ILL_IFTRACE2 (":%d[%d](%la)\n", ix[tctr], tctr,
+ EGLPNUM_TYPENAME_EGlpNumToLf (t[tctr]));
+ tctr++;
+ }
+ }
+ else if (lp->bfeas[i] == 0)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*l, EGLPNUM_TYPENAME_NINFTY))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (t[tctr], *x, *l, y_ij);
+ ix[tctr] = 10 * k + BATOLOWER;
+ ILL_IFTRACE2 (":%d[%d](%la)\n", ix[tctr], tctr,
+ EGLPNUM_TYPENAME_EGlpNumToLf (t[tctr]));
+ tctr++;
+ }
+ }
+ }
+ else if ((dir == VINCREASE && EGLPNUM_TYPENAME_EGlpNumIsLessZero (y_ij)) ||
+ (dir == VDECREASE && EGLPNUM_TYPENAME_EGlpNumIsGreatZero (y_ij)))
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (y_ij))
+ EGLPNUM_TYPENAME_EGlpNumSign (y_ij);
+ ILL_IFTRACE2 (":%d", lp->bfeas[i]);
+ if (lp->bfeas[i] < 0)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (t[tctr], *l, *x, y_ij);
+ ix[tctr] = 10 * k + BBTOLOWER;
+ ILL_IFTRACE2 (":%d[%d](%la)\n", ix[tctr], tctr, EGLPNUM_TYPENAME_EGlpNumToLf (t[tctr]));
+ tctr++;
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*u, EGLPNUM_TYPENAME_INFTY))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (t[tctr], *u, *x, y_ij);
+ ix[tctr] = 10 * k + BBTOUPPER;
+ ILL_IFTRACE2 (":%d[%d](%la)\n", ix[tctr], tctr,
+ EGLPNUM_TYPENAME_EGlpNumToLf (t[tctr]));
+ tctr++;
+ }
+ }
+ else if (lp->bfeas[i] == 0)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*u, EGLPNUM_TYPENAME_INFTY))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (t[tctr], *u, *x, y_ij);
+ ix[tctr] = 10 * k + BBTOUPPER;
+ ILL_IFTRACE2 (":%d[%d](%la)\n", ix[tctr], tctr,
+ EGLPNUM_TYPENAME_EGlpNumToLf (t[tctr]));
+ tctr++;
+ }
+ }
+ }
+ }
+ if (tctr == 0)
+ {
+ rs->ratio_stat = RATIO_FAILED;
+ ILL_CLEANUP;
+ }
+
+ for (i = 0; i < tctr; i++)
+ perm[i] = i;
+ EGLPNUM_TYPENAME_ILLutil_EGlpNum_perm_quicksort (perm, t, tctr);
+
+ EGLPNUM_TYPENAME_EGlpNumZero (lp->upd.c_obj);
+ EGLPNUM_TYPENAME_EGlpNumCopy (rcost, lp->pIdz[eindex]);
+ ILL_IFTRACE2 ("\n%s:%d:%lf", __func__, tctr, EGLPNUM_TYPENAME_EGlpNumToLf (rcost));
+ for (i = 0; i < tctr; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (t_i, t[perm[i]]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (ntmp, t_i);
+ EGLPNUM_TYPENAME_EGlpNumSubTo (ntmp, delta);
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (lp->upd.c_obj, ntmp, rcost);
+ EGLPNUM_TYPENAME_EGlpNumCopy (delta, t_i);
+ ILL_IFTRACE2 (":%d:%lf", perm[i], EGLPNUM_TYPENAME_EGlpNumToLf (delta));
+ /*HHH*/ cbnd = ix[perm[i]] % 10;
+ if (cbnd != BBOUND)
+ {
+ k = ix[perm[i]] / 10;
+ EGLPNUM_TYPENAME_EGlpNumCopy (y_ij, lp->yjz.coef[k]);
+ indx = lp->yjz.indx[k];
+ ILL_IFTRACE2 (":%d", indx);
+ }
+
+ switch (cbnd)
+ {
+ case BBOUND:
+ rs->ratio_stat = RATIO_NOBCHANGE;
+ EGLPNUM_TYPENAME_EGlpNumCopy (rs->tz, t_i);
+ if (dir != VINCREASE)
+ EGLPNUM_TYPENAME_EGlpNumSign (rs->tz);
+ ILL_CLEANUP;
+
+ case BATOLOWER:
+ case BATOUPPER:
+ EGLPNUM_TYPENAME_EGlpNumAddTo (rcost, y_ij);
+ break;
+ case BBTOLOWER:
+ case BBTOUPPER:
+ EGLPNUM_TYPENAME_EGlpNumSubTo (rcost, y_ij);
+ break;
+ }
+ EGLPNUM_TYPENAME_EGlpNumCopyNeg (nrcost, rcost);
+ if ((dir == VINCREASE && EGLPNUM_TYPENAME_EGlpNumIsLeq (nrcost, *dftol)) ||
+ (dir == VDECREASE && EGLPNUM_TYPENAME_EGlpNumIsLeq (rcost, *dftol)))
+ {
+ /* change 5 to -1 if t_i > 0 is required below */
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (t_i) && i > 5)
+ {
+ /* QSlog("pIhell %.5f %d", t_i, i); */
+ EGLPNUM_TYPENAME_EGlpNumDivUiTo (t_i, 2);
+ rs->ratio_stat = RATIO_NEGATIVE;
+ EGLPNUM_TYPENAME_EGlpNumZero (rs->tz);
+ ILL_CLEANUP;
+ }
+ rs->lindex = indx;
+ rs->ratio_stat = RATIO_BCHANGE;
+ if (cbnd == BATOLOWER || cbnd == BBTOLOWER)
+ rs->lvstat = STAT_LOWER;
+ else
+ rs->lvstat = STAT_UPPER;
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (rs->pivotval, y_ij);
+ EGLPNUM_TYPENAME_EGlpNumCopy (rs->tz, t_i);
+ if (dir != VINCREASE)
+ EGLPNUM_TYPENAME_EGlpNumSign (rs->tz);
+ ILL_CLEANUP;
+ }
+ }
+
+CLEANUP:
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_PIPIV, 0, rs->pivotval);
+ ILL_IFTRACE2 (":tctr %d:%d\n", tctr, rs->ratio_stat);
+ lp->upd.tctr = tctr;
+ lp->upd.i = i;
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->upd.tz, t_i);
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->upd.piv, rs->pivotval);
+ if (dir == VDECREASE)
+ EGLPNUM_TYPENAME_EGlpNumSign (lp->upd.c_obj);
+ if (rs->lindex != -1)
+ lp->upd.fs = lp->bfeas[rs->lindex];
+ EGLPNUM_TYPENAME_EGlpNumClearVar (t_i);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (delta);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (y_ij);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (rcost);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (nrcost);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+}
+
+void EGLPNUM_TYPENAME_ILLratio_pII_test (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int eindex,
+ int dir,
+ EGLPNUM_TYPENAME_ratio_res * rs)
+{
+ int i, k, indx, col, ecol;
+ EGLPNUM_TYPE *x, *l, *u, t_max, ayi_max, yi_max, ay_ij, y_ij, t_i, t_z;
+ EGLPNUM_TYPE *pivtol = &(lp->tol->pivot_tol);
+ EGLPNUM_TYPE *pftol = &(lp->tol->pfeas_tol);
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (y_ij);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (ay_ij);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (t_i);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (t_z);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (t_max);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (yi_max);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (ayi_max);
+ /*HHH*/ rs->boundch = 0;
+ rs->lindex = -1;
+ EGLPNUM_TYPENAME_EGlpNumZero (rs->tz);
+ rs->ratio_stat = RATIO_FAILED;
+ rs->lvstat = -1;
+ EGLPNUM_TYPENAME_EGlpNumZero (rs->pivotval);
+ EGLPNUM_TYPENAME_EGlpNumZero (rs->lbound);
+ ecol = lp->nbaz[eindex];
+
+ for (k = 0, EGLPNUM_TYPENAME_EGlpNumCopy (t_max, EGLPNUM_TYPENAME_INFTY); k < lp->yjz.nzcnt; k++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (y_ij, lp->yjz.coef[k]);
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs (ay_ij, y_ij);
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (y_ij, *pivtol))
+ continue;
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (t_i, EGLPNUM_TYPENAME_INFTY);
+ i = lp->yjz.indx[k];
+ x = &(lp->xbz[i]);
+ col = lp->baz[i];
+ l = &(lp->lz[col]);
+ u = &(lp->uz[col]);
+
+ if ((dir == VINCREASE && EGLPNUM_TYPENAME_EGlpNumIsGreatZero (y_ij)) ||
+ (dir == VDECREASE && EGLPNUM_TYPENAME_EGlpNumIsLessZero (y_ij)))
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*l, EGLPNUM_TYPENAME_NINFTY))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (t_i, *x, *l);
+ EGLPNUM_TYPENAME_EGlpNumAddTo (t_i, *pftol);
+ EGLPNUM_TYPENAME_EGlpNumDivTo (t_i, ay_ij);
+ }
+ }
+ else if ((dir == VINCREASE && EGLPNUM_TYPENAME_EGlpNumIsLessZero (y_ij)) ||
+ (dir == VDECREASE && EGLPNUM_TYPENAME_EGlpNumIsGreatZero (y_ij)))
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*u, EGLPNUM_TYPENAME_INFTY))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopySum (t_i, *u, *pftol);
+ EGLPNUM_TYPENAME_EGlpNumSubTo (t_i, *x);
+ EGLPNUM_TYPENAME_EGlpNumDivTo (t_i, ay_ij);
+ }
+ }
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (t_i, EGLPNUM_TYPENAME_INFTY))
+ continue;
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (t_i, t_max))
+ {
+ /*HHH tind = i; yval = fabs (y_ij); tval = t_i - pftol/fabs(y_ij); */
+ EGLPNUM_TYPENAME_EGlpNumCopy (t_max, t_i);
+ }
+ }
+ /* we use yi_max as temporal variable here */
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (yi_max, lp->uz[ecol], lp->lz[ecol]);
+ if (lp->vtype[ecol] == VBOUNDED && EGLPNUM_TYPENAME_EGlpNumIsLeq (yi_max, t_max))
+ {
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (t_max, yi_max);
+ rs->ratio_stat = RATIO_NOBCHANGE;
+ EGLPNUM_TYPENAME_EGlpNumCopy (rs->tz, t_max);
+ if (dir != VINCREASE)
+ EGLPNUM_TYPENAME_EGlpNumSign (rs->tz);
+ ILL_CLEANUP;
+ }
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsLeq (EGLPNUM_TYPENAME_INFTY, t_max))
+ {
+ rs->ratio_stat = RATIO_UNBOUNDED;
+ ILL_CLEANUP;
+ }
+ /*if (EGLPNUM_TYPENAME_EGlpNumIsLess (t_max, EGLPNUM_TYPENAME_zeroLpNum))
+ * QSlog("pIIhell");
+ */
+ indx = -1;
+ EGLPNUM_TYPENAME_EGlpNumZero (t_z);
+ EGLPNUM_TYPENAME_EGlpNumZero (yi_max);
+ EGLPNUM_TYPENAME_EGlpNumZero (ayi_max);
+ ILL_IFTRACE2 (":%d", lp->yjz.nzcnt);
+ for (k = 0; k < lp->yjz.nzcnt; k++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (y_ij, lp->yjz.coef[k]);
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs (ay_ij, y_ij);
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (y_ij, *pivtol))
+ continue;
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (t_i, EGLPNUM_TYPENAME_INFTY);
+ i = lp->yjz.indx[k];
+ x = &(lp->xbz[i]);
+ col = lp->baz[i];
+ l = &(lp->lz[col]);
+ u = &(lp->uz[col]);
+
+ if ((dir == VINCREASE && EGLPNUM_TYPENAME_EGlpNumIsGreatZero (y_ij)) ||
+ (dir == VDECREASE && EGLPNUM_TYPENAME_EGlpNumIsLessZero (y_ij)))
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*l, EGLPNUM_TYPENAME_NINFTY))
+ EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (t_i, *x, *l, ay_ij);
+ }
+ else if ((dir == VINCREASE && EGLPNUM_TYPENAME_EGlpNumIsLessZero (y_ij)) ||
+ (dir == VDECREASE && EGLPNUM_TYPENAME_EGlpNumIsGreatZero (y_ij)))
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*u, EGLPNUM_TYPENAME_INFTY))
+ EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (t_i, *u, *x, ay_ij);
+ }
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsLeq (t_i, t_max))
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (ayi_max, ay_ij))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (yi_max, y_ij);
+ EGLPNUM_TYPENAME_EGlpNumCopy (ayi_max, ay_ij);
+ indx = i;
+ EGLPNUM_TYPENAME_EGlpNumCopy (t_z, t_i);
+ ILL_IFTRACE2 (":%d:%lf:%lf:%lf:%lf", indx, EGLPNUM_TYPENAME_EGlpNumToLf (t_i),
+ EGLPNUM_TYPENAME_EGlpNumToLf (t_max), EGLPNUM_TYPENAME_EGlpNumToLf (ayi_max),
+ EGLPNUM_TYPENAME_EGlpNumToLf (ay_ij));
+ }
+ }
+ }
+
+ if (indx < 0)
+ {
+ rs->ratio_stat = RATIO_FAILED;
+ }
+ else
+ {
+ /*
+ * if (tind != rs->lindex){
+ * HHHprintf ("tmax %e tval = %e yval = %e tind = %d\n", t_max, tval, yval, tind);
+ * HHHprintf ("h tval = %e yval = %e tind = %d\n",rs->tz, yi_max, rs->lindex);
+ * }
+ */
+ ILL_IFTRACE2 (":%d", indx);
+ rs->lindex = indx;
+ EGLPNUM_TYPENAME_EGlpNumCopy (rs->tz, t_z);
+ EGLPNUM_TYPENAME_EGlpNumCopy (rs->pivotval, yi_max);
+ rs->ratio_stat = RATIO_BCHANGE;
+
+ if (dir == VINCREASE)
+ rs->lvstat =
+ (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (yi_max)) ? STAT_LOWER : STAT_UPPER;
+ else
+ rs->lvstat =
+ (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (yi_max)) ? STAT_UPPER : STAT_LOWER;
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (rs->tz))
+ {
+ ILL_IFTRACE2 ("need to change bound, tz=%la\n", EGLPNUM_TYPENAME_EGlpNumToLf (rs->tz));
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs (rs->tz, t_max);
+ EGLPNUM_TYPENAME_EGlpNumDivUiTo (rs->tz, 10);
+ rs->boundch = 1;
+ EGLPNUM_TYPENAME_EGlpNumCopy (rs->lbound, lp->xbz[rs->lindex]);
+ if (rs->lvstat == STAT_LOWER)
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (rs->lbound, rs->tz, ayi_max);
+ else
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (rs->lbound, rs->tz, ayi_max);
+ }
+ if (dir == VDECREASE)
+ EGLPNUM_TYPENAME_EGlpNumSign (rs->tz);
+ }
+CLEANUP:
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_PIIPIV, 0, rs->pivotval);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (y_ij);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ay_ij);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (t_i);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (t_z);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (t_max);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (yi_max);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ayi_max);
+}
+
+#define GET_XY_DRATIOTEST \
+ if (lp->vstat[col] == STAT_UPPER){ \
+ EGLPNUM_TYPENAME_EGlpNumCopyNeg(x,lp->dz[j]);\
+ EGLPNUM_TYPENAME_EGlpNumCopy(y, *zAj);\
+ } \
+ else{ \
+ EGLPNUM_TYPENAME_EGlpNumCopy(x, lp->dz[j]); \
+ EGLPNUM_TYPENAME_EGlpNumCopyNeg(y, *zAj);\
+ } \
+ if (lvstat == STAT_UPPER) \
+ EGLPNUM_TYPENAME_EGlpNumSign(y);
+
+
+void EGLPNUM_TYPENAME_ILLratio_dI_test (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int lindex,
+ int lvstat,
+ EGLPNUM_TYPENAME_ratio_res * rs)
+{
+ int j = 0, k;
+ int col;
+ int cbnd, indx;
+ int tctr = 0;
+ int *perm = lp->upd.perm;
+ int *ix = lp->upd.ix;
+ EGLPNUM_TYPE *t = lp->upd.t;
+ EGLPNUM_TYPE *zAj, x, y, t_j, theta, rcost, delta;
+ EGLPNUM_TYPE *pftol = &(lp->tol->ip_tol);
+ EGLPNUM_TYPE *pivtol = &(lp->tol->pivot_tol);
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (x);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (y);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (t_j);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (theta);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (rcost);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (delta);
+ EGLPNUM_TYPENAME_EGlpNumZero (delta);
+ EGLPNUM_TYPENAME_EGlpNumZero (t_j);
+ EGLPNUM_TYPENAME_EGlpNumZero (rs->tz);
+ /*HHH*/ rs->eindex = -1;
+ rs->ratio_stat = RATIO_FAILED;
+ EGLPNUM_TYPENAME_EGlpNumZero (rs->pivotval);
+
+ for (k = 0; k < lp->zA.nzcnt; k++)
+ {
+ zAj = &(lp->zA.coef[k]);
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (*zAj, *pivtol))
+ continue;
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (t_j, EGLPNUM_TYPENAME_INFTY);
+ j = lp->zA.indx[k];
+ col = lp->nbaz[j];
+
+ if (lp->vtype[col] == VARTIFICIAL || lp->vtype[col] == VFIXED)
+ continue;
+
+ GET_XY_DRATIOTEST;
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (y))
+ {
+ if (lp->dfeas[j] != 0 && lp->vstat[col] != STAT_ZERO)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (t[tctr], x, y);
+ ix[tctr] = 10 * k + BBTOLOWER;
+ tctr++;
+ }
+ else if (lp->vstat[col] == STAT_ZERO)
+ {
+ if (lp->dfeas[j] < 0)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (t[tctr], x, y);
+ ix[tctr] = 10 * k + BBTOLOWER;
+ tctr++;
+ }
+ if (lp->dfeas[j] <= 0)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (t[tctr], x, y);
+ ix[tctr] = 10 * k + BBTOUPPER;
+ tctr++;
+ }
+ }
+ }
+ else
+ {
+ if (lp->dfeas[j] > 0)
+ {
+ if (lp->vstat[col] == STAT_ZERO)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (t[tctr], x, y);
+ ix[tctr] = 10 * k + BATOUPPER;
+ tctr++;
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (t[tctr], x, y);
+ ix[tctr] = 10 * k + BATOLOWER;
+ tctr++;
+ }
+ }
+ else if (lp->dfeas[j] == 0)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (t[tctr], x, y);
+ if (lp->vtype[col] == VBOUNDED)
+ ix[tctr] = 10 * k + BSKIP;
+ else
+ ix[tctr] = 10 * k + BATOLOWER;
+ tctr++;
+ }
+ }
+ }
+
+ if (tctr == 0)
+ {
+ rs->ratio_stat = RATIO_FAILED;
+ ILL_CLEANUP;
+ }
+
+ for (j = 0; j < tctr; j++)
+ perm[j] = j;
+ EGLPNUM_TYPENAME_ILLutil_EGlpNum_perm_quicksort (perm, t, tctr);
+
+ EGLPNUM_TYPENAME_EGlpNumZero (lp->upd.c_obj);
+ EGLPNUM_TYPENAME_EGlpNumCopy (rcost, lp->xbz[lindex]);
+ if (lvstat == STAT_LOWER)
+ EGLPNUM_TYPENAME_EGlpNumSign (rcost);
+ for (j = 0; j < tctr; j++)
+ {
+ cbnd = ix[perm[j]] % 10;
+ if (cbnd == BSKIP)
+ continue;
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (t_j, t[perm[j]]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (x, t_j);
+ EGLPNUM_TYPENAME_EGlpNumSubTo (x, delta);
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (lp->upd.c_obj, x, rcost);
+ EGLPNUM_TYPENAME_EGlpNumCopy (delta, t_j);
+ k = ix[perm[j]] / 10;
+ zAj = &(lp->zA.coef[k]);
+ indx = lp->zA.indx[k];
+
+ if (lp->vstat[lp->nbaz[indx]] == STAT_LOWER
+ || lp->vstat[lp->nbaz[indx]] == STAT_ZERO)
+ EGLPNUM_TYPENAME_EGlpNumCopyNeg (theta, *zAj);
+ else
+ EGLPNUM_TYPENAME_EGlpNumCopy (theta, *zAj);
+
+ if (lvstat == STAT_UPPER)
+ EGLPNUM_TYPENAME_EGlpNumSign (theta);
+
+ switch (cbnd)
+ {
+ case BATOLOWER:
+ case BATOUPPER:
+ EGLPNUM_TYPENAME_EGlpNumSubTo (rcost, theta);
+ break;
+ case BBTOLOWER:
+ case BBTOUPPER:
+ EGLPNUM_TYPENAME_EGlpNumAddTo (rcost, theta);
+ break;
+ }
+ if (EGLPNUM_TYPENAME_EGlpNumIsLeq (rcost, *pftol))
+ {
+ /* if (t_j < 0.0) QSlog("dIhell"); */
+ rs->eindex = indx;
+ EGLPNUM_TYPENAME_EGlpNumCopy (rs->tz, t_j);
+ EGLPNUM_TYPENAME_EGlpNumCopy (rs->pivotval, *zAj);
+ rs->ratio_stat = RATIO_BCHANGE;
+ ILL_CLEANUP;
+ }
+ }
+
+CLEANUP:
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_DIPIV, 0, rs->pivotval);
+ ILL_IFTRACE2 ("%s:tctr %d\n", __func__, tctr);
+ lp->upd.tctr = tctr;
+ lp->upd.i = j;
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs (lp->upd.tz, t_j);
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->upd.piv, rs->pivotval);
+ if (rs->eindex != -1)
+ lp->upd.fs = lp->dfeas[rs->eindex];
+ EGLPNUM_TYPENAME_EGlpNumClearVar (x);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (y);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (t_j);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (theta);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (rcost);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (delta);
+}
+
+void EGLPNUM_TYPENAME_ILLratio_dII_test (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ /*int lindex,*/
+ int lvstat,
+ EGLPNUM_TYPENAME_ratio_res * rs)
+{
+ int j, k, indx;
+ int col, ecol;
+ EGLPNUM_TYPE *zAj, azAj, az_max, x, y, t_j, z_max, t_max, t_z;
+ EGLPNUM_TYPE *dftol = &(lp->tol->dfeas_tol);
+ EGLPNUM_TYPE *pivtol = &(lp->tol->pivot_tol);
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (x);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (y);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (t_j);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (z_max);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (t_max);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (az_max);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (azAj);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (t_z);
+ EGLPNUM_TYPENAME_EGlpNumZero (t_j);
+ rs->coeffch = 0;
+ EGLPNUM_TYPENAME_EGlpNumZero (rs->ecoeff);
+ rs->eindex = -1;
+ rs->ratio_stat = RATIO_FAILED;
+ ILL_IFTRACE2 ("%s:tctr %d\n", __func__, 0);
+ lp->upd.tctr = 0;
+ EGLPNUM_TYPENAME_EGlpNumZero (lp->upd.dty);
+ for (k = 0, EGLPNUM_TYPENAME_EGlpNumCopy (t_max, EGLPNUM_TYPENAME_INFTY); k < lp->zA.nzcnt; k++)
+ {
+ zAj = &(lp->zA.coef[k]);
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (*zAj, *pivtol))
+ continue;
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (t_j, EGLPNUM_TYPENAME_INFTY);
+ j = lp->zA.indx[k];
+ col = lp->nbaz[j];
+
+ if (lp->vtype[col] == VARTIFICIAL || lp->vtype[col] == VFIXED)
+ continue;
+
+ GET_XY_DRATIOTEST;
+
+//#warning adding/substracting tolerances to used value, is it rigght?
+ if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (y))
+ {
+ //t_j = (x + dftol) / y;
+ EGLPNUM_TYPENAME_EGlpNumCopySum (t_j, x, *dftol);
+ EGLPNUM_TYPENAME_EGlpNumDivTo (t_j, y);
+ }
+ else
+ {
+//#warning adding/substracting tolerances to used value, is it rigght?
+ if (lp->vstat[col] == STAT_ZERO)
+ EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (t_j, x, *dftol, y);
+ }
+ //if (t_j == EGLPNUM_TYPENAME_INFTY)
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (t_j, EGLPNUM_TYPENAME_INFTY))
+ continue;
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (t_j, t_max))
+ EGLPNUM_TYPENAME_EGlpNumCopy (t_max, t_j);
+ }
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsLeq (EGLPNUM_TYPENAME_INFTY, t_max))
+ {
+ rs->ratio_stat = RATIO_UNBOUNDED;
+ ILL_CLEANUP;
+ }
+ /* if (t_max < 0.0) QSlog("dIIhell"); */
+
+ indx = -1;
+ EGLPNUM_TYPENAME_EGlpNumZero (t_z);
+ EGLPNUM_TYPENAME_EGlpNumZero (z_max);
+ EGLPNUM_TYPENAME_EGlpNumZero (az_max);
+
+ for (k = 0; k < lp->zA.nzcnt; k++)
+ {
+ zAj = &(lp->zA.coef[k]);
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs (azAj, *zAj);
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (*zAj, *pivtol))
+ continue;
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (t_j, EGLPNUM_TYPENAME_INFTY);
+ j = lp->zA.indx[k];
+ col = lp->nbaz[j];
+
+ if (lp->vtype[col] == VARTIFICIAL || lp->vtype[col] == VFIXED)
+ continue;
+
+ GET_XY_DRATIOTEST;
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (y) || lp->vstat[col] == STAT_ZERO)
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (t_j, x, y);
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsLeq (t_j, t_max) && (EGLPNUM_TYPENAME_EGlpNumIsLess (az_max, azAj)))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (z_max, *zAj);
+ EGLPNUM_TYPENAME_EGlpNumCopy (az_max, azAj);
+ indx = j;
+ EGLPNUM_TYPENAME_EGlpNumCopy (t_z, t_j);
+ }
+ }
+
+
+ if (indx < 0)
+ {
+ rs->ratio_stat = RATIO_FAILED;
+ }
+ else
+ {
+ rs->eindex = indx;
+ EGLPNUM_TYPENAME_EGlpNumCopy (rs->tz, t_z);
+ EGLPNUM_TYPENAME_EGlpNumCopy (rs->pivotval, z_max);
+ rs->ratio_stat = RATIO_BCHANGE;
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (rs->tz))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs (rs->tz, t_max);
+ EGLPNUM_TYPENAME_EGlpNumDivUiTo (rs->tz, 20);
+ rs->coeffch = 1;
+ ecol = lp->nbaz[indx];
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (rs->ecoeff, lp->cz[ecol], lp->dz[indx]);
+ switch (lp->vstat[ecol])
+ {
+ case STAT_LOWER:
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (rs->ecoeff, rs->tz, az_max);
+ break;
+ case STAT_UPPER:
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (rs->ecoeff, rs->tz, az_max);
+ break;
+ default:
+ EGLPNUM_TYPENAME_EGlpNumZero (rs->tz);
+ break;
+ }
+ }
+ }
+
+CLEANUP:
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_DIIPIV, 0, rs->pivotval);
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->upd.piv, rs->pivotval);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (x);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (y);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (t_j);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (z_max);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (t_max);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (t_z);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (az_max);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (azAj);
+}
+
+void EGLPNUM_TYPENAME_ILLratio_longdII_test (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int lindex,
+ int lvstat,
+ EGLPNUM_TYPENAME_ratio_res * rs)
+{
+ int j, k, indx = 0, tctr = 0;
+ int col, ecol;
+ int vs, bnd_exist = 0;
+ int *perm = lp->upd.perm;
+ int *ix = lp->upd.ix;
+ int b_indx = -1;
+ EGLPNUM_TYPE *t = lp->upd.t;
+ EGLPNUM_TYPE *l,
+ *u,
+ *xb,
+ *zAj = 0,
+ x,
+ y,
+ t_j,
+ z_max,
+ t_max, t_z, theta, rcost, delta, zb_val, tb_val, az_max, azb_val, azAj;
+ EGLPNUM_TYPE *pftol = &(lp->tol->pfeas_tol);
+ EGLPNUM_TYPE *dftol = &(lp->tol->dfeas_tol);
+ EGLPNUM_TYPE *pivtol = &(lp->tol->pivot_tol);
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (x);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (azAj);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (y);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (t_j);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (z_max);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (az_max);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (t_max);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (t_z);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (theta);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (rcost);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (delta);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (zb_val);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (azb_val);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (tb_val);
+ EGLPNUM_TYPENAME_EGlpNumZero (t_j);
+ EGLPNUM_TYPENAME_EGlpNumZero (delta);
+ EGLPNUM_TYPENAME_EGlpNumZero (zb_val);
+ EGLPNUM_TYPENAME_EGlpNumZero (azb_val);
+ EGLPNUM_TYPENAME_EGlpNumCopy (tb_val, EGLPNUM_TYPENAME_NINFTY);
+//#warning not sure about THIS line
+ EGLPNUM_TYPENAME_EGlpNumZero (rs->pivotval);
+
+ rs->coeffch = 0;
+ rs->eindex = -1;
+ rs->ratio_stat = RATIO_FAILED;
+
+ ILL_IFTRACE2 ("%s:tctr %d\n", __func__, 0);
+ lp->upd.tctr = 0;
+ lp->upd.i = 0;
+ EGLPNUM_TYPENAME_EGlpNumZero (lp->upd.tz);
+ EGLPNUM_TYPENAME_EGlpNumZero (lp->upd.piv);
+ EGLPNUM_TYPENAME_EGlpNumZero (lp->upd.c_obj);
+ EGLPNUM_TYPENAME_EGlpNumZero (lp->upd.dty);
+
+ xb = &(lp->xbz[lindex]);
+ col = lp->baz[lindex];
+ l = &(lp->lz[col]);
+ u = &(lp->uz[col]);
+ //rcost = (lvstat == STAT_LOWER) ? l - xb : xb - u;
+ if (lvstat == STAT_LOWER)
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (rcost, *l, *xb);
+ else
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (rcost, *xb, *u);
+
+ for (k = 0, EGLPNUM_TYPENAME_EGlpNumCopy (t_max, EGLPNUM_TYPENAME_INFTY); k < lp->zA.nzcnt; k++)
+ {
+ zAj = &(lp->zA.coef[k]);
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (*zAj, *pivtol))
+ continue;
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (t_j, EGLPNUM_TYPENAME_INFTY);
+ j = lp->zA.indx[k];
+ col = lp->nbaz[j];
+
+ if (lp->vtype[col] == VARTIFICIAL || lp->vtype[col] == VFIXED)
+ continue;
+ if (lp->vtype[col] == VBOUNDED)
+ {
+ bnd_exist++;
+ continue;
+ }
+
+ GET_XY_DRATIOTEST;
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (y))
+ {
+ //t_j = (x + dftol) / y;
+//#warning Using tolerances to add to result, is it right?
+ EGLPNUM_TYPENAME_EGlpNumCopySum (t_j, x, *dftol);
+ EGLPNUM_TYPENAME_EGlpNumDivTo (t_j, y);
+ }
+ else
+ {
+ if (lp->vstat[col] == STAT_ZERO)
+ EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (t_j, x, *dftol, y);
+ }
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (t_j, EGLPNUM_TYPENAME_INFTY))
+ continue;
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (t_j, t_max))
+ EGLPNUM_TYPENAME_EGlpNumCopy (t_max, t_j);
+ }
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (t_max))
+ {
+ /*QSlog("dIIhell, %.4f", t_max); */
+ rs->ratio_stat = RATIO_NEGATIVE;
+ ILL_CLEANUP;
+ }
+
+ if (bnd_exist == 0 && EGLPNUM_TYPENAME_EGlpNumIsLeq (EGLPNUM_TYPENAME_INFTY, t_max))
+ {
+ rs->ratio_stat = RATIO_UNBOUNDED;
+ /*
+ * QSlog("x = %.8f, b = %.2f", lp->xbz[lindex], (lvstat == STAT_LOWER ) ? lp->lz[lp->baz[lindex]] : lp->uz[lp->baz[lindex]]);
+ */
+ ILL_CLEANUP;
+ }
+
+ if (bnd_exist != 0)
+ {
+ for (k = 0; k < lp->zA.nzcnt; k++)
+ {
+ zAj = &(lp->zA.coef[k]);
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (*zAj, *pivtol))
+ continue;
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (t_j, EGLPNUM_TYPENAME_INFTY);
+ j = lp->zA.indx[k];
+ col = lp->nbaz[j];
+
+ if (lp->vtype[col] != VBOUNDED)
+ continue;
+
+ GET_XY_DRATIOTEST;
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (y))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (t_j, x, y);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLeq (t_j, t_max))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (t[tctr], t_j);
+ ix[tctr] = k;
+ tctr++;
+ }
+ }
+ }
+ }
+
+ if (tctr != 0)
+ {
+ for (j = 0; j < tctr; j++)
+ perm[j] = j;
+ EGLPNUM_TYPENAME_ILLutil_EGlpNum_perm_quicksort (perm, t, tctr);
+
+ for (j = 0; j < tctr; j++)
+ {
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (t_j, t[perm[j]]);
+ /* we use x as temporal storage */
+ //lp->upd.c_obj += (t_j - delta) * rcost;
+ EGLPNUM_TYPENAME_EGlpNumCopy (x, t_j);
+ EGLPNUM_TYPENAME_EGlpNumSubTo (x, delta);
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (lp->upd.c_obj, x, rcost);
+ EGLPNUM_TYPENAME_EGlpNumCopy (delta, t_j);
+ /*HHH*/ k = ix[perm[j]];
+ zAj = &(lp->zA.coef[k]);
+ indx = lp->zA.indx[k];
+ col = lp->nbaz[indx];
+ l = &(lp->lz[col]);
+ u = &(lp->uz[col]);
+ vs = lp->vstat[col];
+ //theta = (vs == STAT_UPPER) ? (l - u) * zAj : (u - l) * zAj;
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (theta, *l, *u);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (theta, *zAj);
+ if (vs != STAT_UPPER)
+ EGLPNUM_TYPENAME_EGlpNumSign (theta);
+ if (lvstat == STAT_LOWER)
+ EGLPNUM_TYPENAME_EGlpNumAddTo (rcost, theta);
+ else
+ EGLPNUM_TYPENAME_EGlpNumSubTo (rcost, theta);
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsLeq (rcost, *pftol))
+ {
+ rs->eindex = indx;
+ EGLPNUM_TYPENAME_EGlpNumCopy (rs->tz, t_j);
+ EGLPNUM_TYPENAME_EGlpNumCopy (rs->pivotval, *zAj);
+ rs->ratio_stat = RATIO_BCHANGE;
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (rs->tz))
+ {
+ EGLPNUM_TYPENAME_EGlpNumZero (rs->tz);
+ rs->coeffch = 1;
+ //rs->ecoeff = lp->cz[col] - lp->dz[indx];
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (rs->ecoeff, lp->cz[col], lp->dz[indx]);
+ //lp->upd.c_obj += (rs->tz - delta) * rcost; note ts->tz == 0;
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (lp->upd.c_obj, delta, rcost);
+ }
+ ILL_IFTRACE2 ("%s:tctr %d\n", __func__, tctr);
+ lp->upd.tctr = tctr;
+ lp->upd.i = j;
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->upd.tz, rs->tz);
+ ILL_CLEANUP;
+ }
+ }
+ ILL_IFTRACE2 ("%s:tctr %d\n", __func__, tctr);
+ lp->upd.tctr = tctr;
+ lp->upd.i = tctr;
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->upd.tz, t_j);
+ EGLPNUM_TYPENAME_EGlpNumCopy (zb_val, *zAj);
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs (azb_val, zb_val);
+ EGLPNUM_TYPENAME_EGlpNumCopy (tb_val, t_j);
+ b_indx = indx;
+ }
+
+ if (bnd_exist != 0 && EGLPNUM_TYPENAME_EGlpNumIsLeq (EGLPNUM_TYPENAME_INFTY, t_max))
+ {
+ rs->ratio_stat = RATIO_UNBOUNDED;
+ /* QSlog("rcost: %.8f", rcost); */
+ ILL_CLEANUP;
+ }
+
+ EGLPNUM_TYPENAME_EGlpNumZero (z_max);
+ EGLPNUM_TYPENAME_EGlpNumZero (az_max);
+ indx = -1;
+ EGLPNUM_TYPENAME_EGlpNumZero (t_z);
+ for (k = 0; k < lp->zA.nzcnt; k++)
+ {
+ zAj = &(lp->zA.coef[k]);
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs (azAj, *zAj);
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (*zAj, *pivtol))
+ continue;
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (t_j, EGLPNUM_TYPENAME_INFTY);
+ j = lp->zA.indx[k];
+ col = lp->nbaz[j];
+
+ if (lp->vtype[col] == VARTIFICIAL || lp->vtype[col] == VFIXED ||
+ lp->vtype[col] == VBOUNDED)
+ continue;
+
+ GET_XY_DRATIOTEST;
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (y) || lp->vstat[col] == STAT_ZERO)
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (t_j, x, y);
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsLeq (t_j, t_max))
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (az_max, azAj))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (z_max, *zAj);
+ EGLPNUM_TYPENAME_EGlpNumCopy (az_max, azAj);
+ indx = j;
+ EGLPNUM_TYPENAME_EGlpNumCopy (t_z, t_j);
+ }
+ }
+ }
+
+ if (indx < 0)
+ {
+ rs->ratio_stat = RATIO_FAILED;
+ ILL_CLEANUP;
+ }
+ if ((tctr == 0) || (EGLPNUM_TYPENAME_EGlpNumIsLessZero (tb_val)) ||
+ (tctr != 0 && EGLPNUM_TYPENAME_EGlpNumIsLeq (tb_val, t_z) &&
+ EGLPNUM_TYPENAME_EGlpNumIsLeq (azb_val, az_max)))
+ {
+ /* we use x as temporal vvariable */
+ /* lp->upd.c_obj += (t_z - delta) * rcost; */
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (x, t_z, delta);
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (lp->upd.c_obj, x, rcost);
+ EGLPNUM_TYPENAME_EGlpNumCopy (delta, t_z);
+ rs->eindex = indx;
+ EGLPNUM_TYPENAME_EGlpNumCopy (rs->tz, t_z);
+ EGLPNUM_TYPENAME_EGlpNumCopy (rs->pivotval, z_max);
+ rs->ratio_stat = RATIO_BCHANGE;
+ }
+ /* For now */
+ else if (tctr != 0)
+ {
+ rs->eindex = b_indx;
+ EGLPNUM_TYPENAME_EGlpNumCopy (rs->tz, tb_val);
+ EGLPNUM_TYPENAME_EGlpNumCopy (rs->pivotval, zb_val);
+ rs->ratio_stat = RATIO_BCHANGE;
+ lp->upd.i -= 1;
+ }
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (rs->tz))
+ {
+ /* if (tctr != 0) QSlog("despite long step"); */
+ /* rs->tz = fabs (t_max / 20.0); */
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs (rs->tz, t_max);
+ EGLPNUM_TYPENAME_EGlpNumDivUiTo (rs->tz, 20);
+ rs->coeffch = 1;
+
+ ecol = lp->nbaz[indx];
+ if (lp->vstat[ecol] == STAT_LOWER)
+ {
+ /*rs->ecoeff = lp->cz[ecol] - lp->dz[indx] + rs->tz * fabs (z_max); */
+ EGLPNUM_TYPENAME_EGlpNumCopy (rs->ecoeff, az_max);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (rs->ecoeff, rs->tz);
+ EGLPNUM_TYPENAME_EGlpNumAddTo (rs->ecoeff, lp->cz[ecol]);
+ EGLPNUM_TYPENAME_EGlpNumSubTo (rs->ecoeff, lp->dz[indx]);
+ }
+ else if (lp->vstat[ecol] == STAT_UPPER)
+ {
+ /*rs->ecoeff = lp->cz[ecol] - lp->dz[indx] - rs->tz * fabs (z_max); */
+ EGLPNUM_TYPENAME_EGlpNumCopy (rs->ecoeff, az_max);
+ EGLPNUM_TYPENAME_EGlpNumMultTo (rs->ecoeff, rs->tz);
+ EGLPNUM_TYPENAME_EGlpNumSign (rs->ecoeff);
+ EGLPNUM_TYPENAME_EGlpNumAddTo (rs->ecoeff, lp->cz[ecol]);
+ EGLPNUM_TYPENAME_EGlpNumSubTo (rs->ecoeff, lp->dz[indx]);
+ }
+ else
+ {
+ /*rs->ecoeff = lp->cz[ecol] - lp->dz[indx]; */
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (rs->ecoeff, lp->cz[ecol], lp->dz[indx]);
+ EGLPNUM_TYPENAME_EGlpNumZero (rs->tz);
+ }
+ /* we use x as temporal storage */
+ /*lp->upd.c_obj += (rs->tz - delta) * rcost; */
+ EGLPNUM_TYPENAME_EGlpNumCopy (x, rs->tz);
+ EGLPNUM_TYPENAME_EGlpNumSubTo (x, delta);
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (lp->upd.c_obj, x, rcost);
+ }
+
+CLEANUP:
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_DIIPIV, 0, rs->pivotval);
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->upd.piv, rs->pivotval);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (x);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (y);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (t_j);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (z_max);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (az_max);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (t_max);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (t_z);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (theta);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (rcost);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (delta);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (zb_val);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (azb_val);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (tb_val);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (azAj);
+}
+
+void EGLPNUM_TYPENAME_ILLratio_pivotin_test (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int *rlist,
+ int rcnt,
+ EGLPNUM_TYPENAME_ratio_res * rs)
+{
+ int i, k, col;
+ EGLPNUM_TYPE *x, *l, *u;
+ EGLPNUM_TYPE ay_ij,
+ at_i, at_l, at_u, ayi_max, y_ij, t_i, t_l, t_u, t_max, yi_max;
+ EGLPNUM_TYPE *pivtol = &(lp->tol->pivot_tol);
+
+ if (rcnt <= 0 || rs == NULL)
+ return;
+ EGLPNUM_TYPENAME_EGlpNumInitVar (ay_ij);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (at_i);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (at_l);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (at_u);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (ayi_max);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (t_max);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (y_ij);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (t_i);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (t_l);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (t_u);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (yi_max);
+ rs->boundch = 0;
+ rs->lindex = -1;
+ EGLPNUM_TYPENAME_EGlpNumZero (rs->tz);
+ rs->ratio_stat = RATIO_FAILED;
+ rs->lvstat = -1;
+ EGLPNUM_TYPENAME_EGlpNumZero (rs->pivotval);
+ EGLPNUM_TYPENAME_EGlpNumZero (rs->lbound);
+
+ for (i = 0; i < rcnt; i++)
+ lp->iwork[rlist[i]] = 1;
+
+ for (k = 0, EGLPNUM_TYPENAME_EGlpNumCopy (t_max, EGLPNUM_TYPENAME_INFTY); k < lp->yjz.nzcnt; k++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (y_ij, lp->yjz.coef[k]);
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (y_ij, *pivtol))
+ continue;
+
+ i = lp->yjz.indx[k];
+ if (lp->iwork[lp->baz[i]] == 1)
+ continue;
+ x = &(lp->xbz[i]);
+ col = lp->baz[i];
+ l = &(lp->lz[col]);
+ u = &(lp->uz[col]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (t_u, EGLPNUM_TYPENAME_INFTY);
+ EGLPNUM_TYPENAME_EGlpNumCopy (at_u, EGLPNUM_TYPENAME_INFTY);
+ EGLPNUM_TYPENAME_EGlpNumCopy (t_l, EGLPNUM_TYPENAME_NINFTY);
+ EGLPNUM_TYPENAME_EGlpNumCopy (at_l, EGLPNUM_TYPENAME_INFTY);
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*l, EGLPNUM_TYPENAME_NINFTY))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (t_l, *x, *l, y_ij);
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs (at_l, t_l);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (at_l, t_max))
+ EGLPNUM_TYPENAME_EGlpNumCopy (t_max, at_l);
+ }
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*u, EGLPNUM_TYPENAME_INFTY))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (t_u, *x, *u, y_ij);
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs (at_u, t_u);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (at_u, t_max))
+ EGLPNUM_TYPENAME_EGlpNumCopy (t_max, at_u);
+ }
+ }
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsLeq (EGLPNUM_TYPENAME_INFTY, t_max))
+ {
+ rs->ratio_stat = RATIO_UNBOUNDED;
+ ILL_CLEANUP;
+ }
+
+ EGLPNUM_TYPENAME_EGlpNumZero (yi_max);
+ EGLPNUM_TYPENAME_EGlpNumZero (ayi_max);
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (t_max, 101);
+ EGLPNUM_TYPENAME_EGlpNumDivUiTo (t_max, 100);
+ for (k = 0; k < lp->yjz.nzcnt; k++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (y_ij, lp->yjz.coef[k]);
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs (ay_ij, y_ij);
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (y_ij, *pivtol))
+ continue;
+
+ i = lp->yjz.indx[k];
+ if (lp->iwork[lp->baz[i]] == 1)
+ continue;
+ x = &(lp->xbz[i]);
+ col = lp->baz[i];
+ l = &(lp->lz[col]);
+ u = &(lp->uz[col]);
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (t_u, EGLPNUM_TYPENAME_INFTY);
+ EGLPNUM_TYPENAME_EGlpNumCopy (at_u, t_u);
+ EGLPNUM_TYPENAME_EGlpNumCopy (t_l, EGLPNUM_TYPENAME_NINFTY);
+ EGLPNUM_TYPENAME_EGlpNumCopy (at_l, t_u);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*l, EGLPNUM_TYPENAME_NINFTY))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (t_l, *x, *l, y_ij);
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs (at_l, t_l);
+ }
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*u, EGLPNUM_TYPENAME_INFTY))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyDiffRatio (t_u, *x, *u, y_ij);
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs (at_u, t_u);
+ }
+ //t_i = (fabs (t_l) < fabs (t_u)) ? t_l : t_u;
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (at_l, at_u))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (t_i, t_l);
+ EGLPNUM_TYPENAME_EGlpNumCopy (at_i, at_l);
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (t_i, t_u);
+ EGLPNUM_TYPENAME_EGlpNumCopy (at_i, at_u);
+ }
+ /*if (fabs (t_i) <= t_max + t_max * (1.0e-2)) */
+ if (EGLPNUM_TYPENAME_EGlpNumIsLeq (at_i, t_max))
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (ayi_max, ay_ij))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (yi_max, y_ij);
+ EGLPNUM_TYPENAME_EGlpNumCopy (ayi_max, ay_ij);
+ rs->lindex = i;
+ EGLPNUM_TYPENAME_EGlpNumCopy (rs->tz, t_i);
+ rs->lvstat = (EGLPNUM_TYPENAME_EGlpNumIsLess (at_l, at_u)) ? STAT_LOWER : STAT_UPPER;
+ }
+ }
+ }
+
+ if (rs->lindex < 0)
+ {
+ rs->ratio_stat = RATIO_FAILED;
+ }
+ else
+ {
+ rs->ratio_stat = RATIO_BCHANGE;
+ EGLPNUM_TYPENAME_EGlpNumCopy (rs->pivotval, yi_max);
+ }
+CLEANUP:
+ for (i = 0; i < rcnt; i++)
+ lp->iwork[rlist[i]] = 0;
+ EGLPNUM_TYPENAME_EGlpNumClearVar (t_max);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ay_ij);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (at_i);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (at_l);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (at_u);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ayi_max);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (y_ij);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (t_i);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (t_l);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (t_u);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (yi_max);
+ return;
+}
diff --git a/qsopt_ex/ratio.h b/qsopt_ex/ratio.h
new file mode 100644
index 0000000..ff8abfd
--- /dev/null
+++ b/qsopt_ex/ratio.h
@@ -0,0 +1,73 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* $RCSfile: ratio_EGLPNUM_TYPENAME.h,v $ $Revision: 1.3 $ $Date: 2003/11/05 16:57:39 $" */
+#ifndef EGLPNUM_TYPENAME___RATIO_H
+#define EGLPNUM_TYPENAME___RATIO_H
+#include "basicdefs.h"
+typedef struct EGLPNUM_TYPENAME_ratio_res
+{
+ EGLPNUM_TYPE tz;
+ int eindex;
+ int lindex;
+ int lvstat;
+ int ratio_stat;
+ int boundch;
+ int coeffch;
+ EGLPNUM_TYPE lbound;
+ EGLPNUM_TYPE ecoeff;
+ EGLPNUM_TYPE pivotval;
+}
+EGLPNUM_TYPENAME_ratio_res;
+
+void EGLPNUM_TYPENAME_ILLratio_pI_test (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ int const eindex,
+ int const dir,
+ EGLPNUM_TYPENAME_ratio_res * const rs),
+ EGLPNUM_TYPENAME_ILLratio_pII_test (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ int const eindex,
+ int const dir,
+ EGLPNUM_TYPENAME_ratio_res * const rs),
+ EGLPNUM_TYPENAME_ILLratio_dI_test (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ int const lindex,
+ int const lvstat,
+ EGLPNUM_TYPENAME_ratio_res * const rs),
+ EGLPNUM_TYPENAME_ILLratio_dII_test (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ /*int const lindex,*/
+ int const lvstat,
+ EGLPNUM_TYPENAME_ratio_res * const rs),
+ EGLPNUM_TYPENAME_ILLratio_longdII_test (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ int const lindex,
+ int const lvstat,
+ EGLPNUM_TYPENAME_ratio_res * const rs),
+ EGLPNUM_TYPENAME_ILLratio_pivotin_test (
+ EGLPNUM_TYPENAME_lpinfo * const lp,
+ int *const rlist,
+ int const rcnt,
+ EGLPNUM_TYPENAME_ratio_res * const rs);
+
+#endif /* EGLPNUM_TYPENAME___RATIO_H */
diff --git a/qsopt_ex/rawlp.c b/qsopt_ex/rawlp.c
new file mode 100644
index 0000000..d0472bc
--- /dev/null
+++ b/qsopt_ex/rawlp.c
@@ -0,0 +1,1765 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: rawlp.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+/****************************************************************************/
+/* DataStructure and routines to deal with raw lp information as read */
+/* from mps or lp files. */
+/****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <math.h>
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "eg_lpnum.h"
+#include "eg_io.h"
+
+#include "sortrus_EGLPNUM_TYPENAME.h"
+#include "rawlp_EGLPNUM_TYPENAME.h"
+#include "allocrus.h"
+#include "except.h"
+#include "util.h"
+
+
+static int TRACE = 0;
+
+ILL_PTRWORLD_ROUTINES (EGLPNUM_TYPENAME_colptr, colptralloc, colptr_bulkalloc, colptrfree)
+ILL_PTRWORLD_LISTFREE_ROUTINE (EGLPNUM_TYPENAME_colptr, colptr_listfree, colptrfree)
+ILL_PTRWORLD_LEAKS_ROUTINE (EGLPNUM_TYPENAME_colptr, colptr_check_leaks, this_val, int)
+ const int EGLPNUM_TYPENAME_ILL_SOS_TYPE1 = 1;
+ const int EGLPNUM_TYPENAME_ILL_SOS_TYPE2 = 2;
+
+ static void ILLprt_EGlpNum (
+ FILE * f,
+ EGLPNUM_TYPE * d)
+{
+ if (EGLPNUM_TYPENAME_EGlpNumIsLeq (EGLPNUM_TYPENAME_ILL_MAXDOUBLE, *d))
+ {
+ fprintf (f, "MAX_DOUBLE");
+ }
+ else
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsLeq (*d, EGLPNUM_TYPENAME_ILL_MINDOUBLE))
+ {
+ fprintf (f, "-MAX_DOUBLE");
+ }
+ else
+ {
+ fprintf (f, "%f", EGLPNUM_TYPENAME_EGlpNumToLf (*d));
+ }
+ }
+}
+
+static int ILLraw_check_bounds (
+ EGLPNUM_TYPENAME_rawlpdata * lp);
+
+void EGLPNUM_TYPENAME_ILLinit_rawlpdata (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ EGLPNUM_TYPENAME_qserror_collector * collector)
+{
+ if (lp)
+ {
+ lp->name = 0;
+ lp->ncols = 0;
+ lp->nrows = 0;
+ lp->cols = 0;
+ lp->rowsense = 0;
+ lp->rhsname = 0;
+ lp->rhs = 0;
+ lp->rhsind = 0;
+ lp->rangesname = 0;
+ lp->rangesind = 0;
+ lp->ranges = 0;
+ lp->boundsname = 0;
+ lp->lbind = 0;
+ lp->ubind = 0;
+ lp->lower = 0;
+ lp->upper = 0;
+ lp->intmarker = 0;
+ lp->colsize = 0;
+ lp->sensesize = 0;
+ lp->intsize = 0;
+ lp->rhssize = 0;
+ lp->refrow = NULL;
+ lp->is_sos_size = 0;
+ lp->is_sos_member = NULL;
+ lp->nsos_member = 0;
+ lp->sos_weight_size = 0;
+ lp->sos_weight = NULL;
+ lp->sos_col_size = 0;
+ lp->sos_col = NULL;
+ lp->nsos = 0;
+ lp->sos_setsize = 0;
+ lp->sos_set = NULL;
+ ILLsymboltab_init (&lp->coltab);
+ ILLsymboltab_init (&lp->rowtab);
+ lp->objindex = -1;
+ lp->objsense = EGLPNUM_TYPENAME_ILL_MIN;
+ lp->refrowind = -1; /* undefined */
+ ILLptrworld_init (&lp->ptrworld);
+ lp->error_collector = collector;
+ }
+}
+
+void EGLPNUM_TYPENAME_ILLraw_clear_matrix (
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+ int i;
+ EGLPNUM_TYPENAME_colptr *next, *curr;
+
+ if ((lp != NULL) && (lp->cols != NULL))
+ {
+ for (i = 0; i < lp->ncols; i++)
+ {
+ {
+ curr = lp->cols[i];
+ while (curr)
+ {
+ next = curr->next;
+ EGLPNUM_TYPENAME_EGlpNumClearVar ((curr->coef));
+ colptrfree (&(lp->ptrworld), curr);
+ curr = next;
+ }
+ }
+ //colptr_listfree (&lp->ptrworld, lp->cols[i]);
+ lp->cols[i] = NULL;
+ }
+ }
+}
+
+void EGLPNUM_TYPENAME_ILLfree_rawlpdata (
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+ int total, onlist;
+ EGLPNUM_TYPENAME_colptr *next, *curr;
+
+ if (lp)
+ {
+ ILL_IFFREE (lp->name, char);
+
+ ILLsymboltab_free (&lp->rowtab);
+ ILLsymboltab_free (&lp->coltab);
+ ILL_IFFREE (lp->rowsense, char);
+
+ EGLPNUM_TYPENAME_ILLraw_clear_matrix (lp);
+ ILL_IFFREE (lp->cols, EGLPNUM_TYPENAME_colptr *);
+ {
+ curr = lp->ranges;
+ while (curr)
+ {
+ next = curr->next;
+ EGLPNUM_TYPENAME_EGlpNumClearVar ((curr->coef));
+ colptrfree (&(lp->ptrworld), curr);
+ curr = next;
+ }
+ }
+ //colptr_listfree (&lp->ptrworld, lp->ranges);
+ if (colptr_check_leaks (&lp->ptrworld, &total, &onlist))
+ {
+ QSlog("WARNING: %d outstanding colptrs", total - onlist);
+ }
+ ILLptrworld_delete (&lp->ptrworld);
+ ILL_IFFREE (lp->rhsname, char);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->rhs);
+ ILL_IFFREE (lp->rhsind, char);
+ ILL_IFFREE (lp->rangesname, char);
+ ILL_IFFREE (lp->rangesind, char);
+ ILL_IFFREE (lp->boundsname, char);
+ ILL_IFFREE (lp->lbind, char);
+ ILL_IFFREE (lp->ubind, char);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->lower);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->upper);
+ ILL_IFFREE (lp->intmarker, char);
+ ILL_IFFREE (lp->refrow, char);
+ ILL_IFFREE (lp->is_sos_member, int);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->sos_weight);
+ ILL_IFFREE (lp->sos_col, int);
+
+ ILL_IFFREE (lp->sos_set, EGLPNUM_TYPENAME_sosptr);
+ EGLPNUM_TYPENAME_ILLinit_rawlpdata (lp, NULL);
+ }
+}
+
+const char *EGLPNUM_TYPENAME_ILLraw_rowname (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ int i)
+{
+ const char *name = NULL;
+
+ ILL_FAILfalse_no_rval ((i >= 0) && (i < lp->nrows), "index out of range");
+ ILL_FAILfalse_no_rval (lp->nrows == lp->rowtab.tablesize,
+ "tab and lp must be in synch");
+ name = ILLsymboltab_get (&lp->rowtab, i);
+CLEANUP:
+ return name;
+}
+const char *EGLPNUM_TYPENAME_ILLraw_colname (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ int i)
+{
+ const char *name = NULL;
+
+ ILL_FAILfalse_no_rval ((i >= 0) && (i < lp->ncols), "index out of range");
+ ILL_FAILfalse_no_rval (lp->ncols == lp->coltab.tablesize,
+ "tab and lp must be in synch");
+ name = ILLsymboltab_get (&lp->coltab, i);
+CLEANUP:
+ return name;
+}
+
+int EGLPNUM_TYPENAME_ILLraw_add_col (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ const char *name,
+ int intmarker)
+{
+ int rval = 0;
+ int pindex, hit;
+
+ rval = ILLsymboltab_register (&lp->coltab, name, -1, &pindex, &hit);
+ rval = rval || hit;
+ ILL_CLEANUP_IF (rval);
+ if (lp->ncols >= lp->colsize)
+ {
+ lp->colsize *= 1.3;
+ lp->colsize += 1000;
+ if (lp->colsize < lp->ncols + 1)
+ lp->colsize = lp->ncols + 1;
+ lp->cols = EGrealloc (lp->cols, lp->colsize * sizeof (EGLPNUM_TYPENAME_colptr *));
+ //rval = rval || ILLutil_reallocrus_scale (&lp->cols,
+ // &lp->colsize, lp->ncols + 1, 1.3,
+ // sizeof (EGLPNUM_TYPENAME_colptr *));
+ }
+ if (lp->ncols >= lp->intsize)
+ {
+ lp->intsize *= 1.3;
+ lp->intsize += 1000;
+ if (lp->intsize < lp->ncols + 1)
+ lp->intsize = lp->ncols + 1;
+ lp->intmarker = EGrealloc (lp->intmarker, lp->intsize * sizeof (char));
+ //rval = rval || ILLutil_reallocrus_scale ((void **) &lp->intmarker,
+ // &lp->intsize, lp->ncols + 1,
+ // 1.3, sizeof (char));
+ }
+ if (lp->ncols >= lp->is_sos_size)
+ {
+ lp->is_sos_size *= 1.3;
+ lp->is_sos_size += 1000;
+ if (lp->is_sos_size < lp->ncols + 1)
+ lp->is_sos_size = lp->ncols + 1;
+ lp->is_sos_member = EGrealloc (lp->is_sos_member,
+ sizeof (int) * lp->is_sos_size);
+ //rval = rval || ILLutil_reallocrus_scale ((void **) &lp->is_sos_member,
+ // &lp->is_sos_size, lp->ncols + 1,
+ // 1.3, sizeof (int));
+ }
+ ILL_CLEANUP_IF (rval);
+ lp->cols[lp->ncols] = 0;
+ lp->is_sos_member[lp->ncols] = -1;
+ lp->intmarker[lp->ncols] = intmarker;
+ lp->ncols++;
+CLEANUP:
+ ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLraw_add_col");
+}
+
+int EGLPNUM_TYPENAME_ILLraw_init_rhs (
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+ int i, rval = 0;
+
+ ILL_FAILfalse (lp->rhsind == NULL, "Should be called exactly once");
+ if (lp->nrows > 0)
+ {
+ ILL_SAFE_MALLOC (lp->rhsind, lp->nrows, char);
+
+ for (i = 0; i < lp->nrows; i++)
+ {
+ lp->rhsind[i] = (char) 0;
+ }
+ }
+CLEANUP:
+ ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLraw_init_rhs");
+}
+
+int EGLPNUM_TYPENAME_ILLraw_init_ranges (
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+ int i, rval = 0;
+
+ ILL_FAILfalse (lp->rangesind == NULL, "Should be called exactly once");
+ if (lp->nrows > 0)
+ {
+ ILL_SAFE_MALLOC (lp->rangesind, lp->nrows, char);
+
+ for (i = 0; i < lp->nrows; i++)
+ {
+ lp->rangesind[i] = (char) 0;
+ }
+ }
+CLEANUP:
+ ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLraw_init_ranges");
+}
+
+int EGLPNUM_TYPENAME_ILLraw_add_col_coef (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ int colind,
+ int rowind,
+ EGLPNUM_TYPE coef)
+{
+ EGLPNUM_TYPENAME_colptr *cp = EGLPNUM_TYPENAME_ILLcolptralloc (&lp->ptrworld);
+
+ if (!cp)
+ {
+ return 1;
+ }
+ cp->this_val = rowind;
+ EGLPNUM_TYPENAME_EGlpNumCopy (cp->coef, coef);
+ cp->next = lp->cols[colind];
+ lp->cols[colind] = cp;
+ return 0;
+}
+
+
+int EGLPNUM_TYPENAME_ILLraw_add_ranges_coef (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ int rowind,
+ EGLPNUM_TYPE coef)
+{
+ EGLPNUM_TYPENAME_colptr *cp = EGLPNUM_TYPENAME_ILLcolptralloc (&lp->ptrworld);
+
+ if (!cp)
+ {
+ return 1;
+ }
+ cp->this_val = rowind;
+ EGLPNUM_TYPENAME_EGlpNumCopy (cp->coef, coef);
+ cp->next = lp->ranges;
+ lp->ranges = cp;
+ lp->rangesind[rowind] = (char) 1;
+ return 0;
+}
+
+int EGLPNUM_TYPENAME_ILLraw_add_sos (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ int tp)
+{
+ int rval = 0;
+ EGLPNUM_TYPENAME_sosptr *sos, *bef;
+
+ if (lp->nsos >= lp->sos_setsize)
+ {
+ lp->sos_setsize *= 1.3;
+ lp->sos_setsize += 1000;
+ if (lp->sos_setsize < lp->nsos + 1)
+ lp->sos_setsize = lp->nsos + 1;
+ lp->sos_set = EGrealloc (lp->sos_set, sizeof (EGLPNUM_TYPENAME_sosptr *) * lp->sos_setsize);
+ //if (ILLutil_reallocrus_scale ((void **) &lp->sos_set,
+ // &lp->sos_setsize, lp->nsos + 1, 1.3,
+ // sizeof (EGLPNUM_TYPENAME_sosptr *)))
+ //{
+ // ILL_CLEANUP_IF (rval);
+ //}
+ }
+ sos = lp->sos_set + lp->nsos;
+ sos->nelem = 0;
+ sos->type = tp;
+ if (lp->nsos == 0)
+ {
+ sos->first = 0;
+ }
+ else
+ {
+ bef = &(lp->sos_set[lp->nsos - 1]);
+ sos->first = bef->first + bef->nelem;
+ }
+ lp->nsos++;
+//CLEANUP:
+ ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLraw_add_sos");
+}
+
+int EGLPNUM_TYPENAME_ILLraw_is_mem_other_sos (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ int colind)
+{
+ return (lp->is_sos_member[colind] >= 0) &&
+ (lp->is_sos_member[colind] != (lp->nsos - 1));
+}
+
+int EGLPNUM_TYPENAME_ILLraw_add_sos_member (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ int colind)
+{
+ int rval = 0;
+
+ ILL_FAILfalse (lp->nsos > 0, "we should have called EGLPNUM_TYPENAME_ILLraw_add_sos earlier");
+ ILL_FAILtrue (EGLPNUM_TYPENAME_ILLraw_is_mem_other_sos (lp, colind),
+ "colind is member of another sos set");
+
+ if (lp->is_sos_member[colind] == -1)
+ {
+ if (lp->nsos_member >= lp->sos_weight_size)
+ {
+ lp->sos_weight_size *= 1.3;
+ lp->sos_weight_size += 1000;
+ if (lp->sos_weight_size < lp->nsos_member + 1)
+ lp->sos_weight_size = lp->nsos_member + 1;
+ lp->sos_weight = EGrealloc (lp->sos_weight,
+ lp->sos_weight_size * sizeof (double));
+ //if (ILLutil_reallocrus_scale ((void **) &lp->sos_weight,
+ // &lp->sos_weight_size,
+ // lp->nsos_member + 1, 1.3, sizeof (double)))
+ //{
+ // ILL_CLEANUP_IF (rval);
+ //}
+ }
+ if (lp->nsos_member >= lp->sos_col_size)
+ {
+ lp->sos_col_size *= 1.3;
+ lp->sos_col_size += 1000;
+ if (lp->sos_col_size < lp->nsos_member + 1)
+ lp->sos_col_size = lp->nsos_member + 1;
+ lp->sos_col = EGrealloc (lp->sos_col, sizeof (int) * lp->sos_col_size);
+ //if (ILLutil_reallocrus_scale ((void **) &lp->sos_col,
+ // &lp->sos_col_size,
+ // lp->nsos_member + 1, 1.3, sizeof (int)))
+ //{
+ // ILL_CLEANUP_IF (rval);
+ //}
+ }
+ lp->sos_col[lp->nsos_member] = colind;
+ lp->sos_set[lp->nsos - 1].nelem++;
+ lp->is_sos_member[colind] = lp->nsos - 1;
+ lp->nsos_member++;
+ }
+CLEANUP:
+ ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLraw_add_sos_member");
+}
+
+
+int EGLPNUM_TYPENAME_ILLraw_add_row (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ const char *name,
+ int sense,
+ const EGLPNUM_TYPE rhs)
+{
+ int pindex, hit, rval = 0;
+
+ rval = ILLsymboltab_register (&lp->rowtab, name, -1, &pindex, &hit);
+ rval = rval || hit;
+ ILL_CLEANUP_IF (rval);
+ if (lp->nrows >= lp->sensesize)
+ {
+ lp->sensesize *= 1.3;
+ lp->sensesize += 1000;
+ if (lp->sensesize < lp->nrows + 1)
+ lp->sensesize = lp->nrows + 1;
+ lp->rowsense = EGrealloc (lp->rowsense, sizeof (char) * lp->sensesize);
+ //if (ILLutil_reallocrus_scale ((void **) &lp->rowsense,
+ // &lp->sensesize, lp->nrows + 1,
+ // 1.3, sizeof (char)))
+ //{
+ // ILL_CLEANUP_IF (rval);
+ //}
+ }
+ if (lp->nrows >= lp->rhssize)
+ {
+ if (lp->rhssize + 1000 < (lp->nrows + 1) * 1.3)
+ lp->rhssize = (lp->nrows + 1) * 1.3;
+ else
+ lp->rhssize += 1000;
+ EGLPNUM_TYPENAME_EGlpNumReallocArray (&(lp->rhs), lp->rhssize);
+ }
+ lp->rowsense[lp->nrows] = sense;
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->rhs[lp->nrows], rhs);
+ lp->nrows++;
+
+CLEANUP:
+ ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLraw_add_row");
+}
+
+static int ILLcheck_rawlpdata (
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+ int i, col, rval = 0;
+ int si, *perm = NULL;
+ const char *c1, *c2;
+ EGLPNUM_TYPENAME_sosptr *set;
+
+ ILL_FAILfalse (lp, "lp must not be NULL");
+
+ /* check
+ * *) that there is at least one variable
+ * *) that the weights in all SOS sets are distinct
+ * *) all sos members are non integer variables
+ * *) sos set members have distint weights
+ * *) objindex is not -1
+ * *) INVARIANT: rowname[objindex] != NULL
+ * *) INVARIANT: upper/lower arrays are filled in
+ * *) INVARIANT: if col or rownames != NULL then
+ * all their elements are not NULL
+ */
+ if (lp->ncols < 1)
+ {
+ return EGLPNUM_TYPENAME_ILLdata_error (lp->error_collector, "There are no variables.");
+ }
+ if (lp->objindex == -1)
+ {
+ return EGLPNUM_TYPENAME_ILLdata_error (lp->error_collector, "There is no objective fct.");
+ }
+ ILL_FAILfalse (EGLPNUM_TYPENAME_ILLraw_rowname (lp, lp->objindex) != NULL,
+ "must have objective name");
+ if (lp->nsos_member > 1)
+ {
+ ILL_SAFE_MALLOC (perm, lp->nsos_member, int);
+
+ for (si = 0; si < lp->nsos; si++)
+ {
+ set = lp->sos_set + si;
+ for (i = 0; i < set->nelem; i++)
+ {
+ col = lp->sos_col[set->first + i];
+ if (lp->intmarker[col])
+ {
+ rval = EGLPNUM_TYPENAME_ILLdata_error (lp->error_collector,
+ "SOS set member \"%s\" is an %s.\n",
+ EGLPNUM_TYPENAME_ILLraw_colname (lp, col),
+ "integer/binary variable");
+ }
+ }
+ if (set->nelem > 1)
+ {
+ for (i = 0; i < set->nelem; i++)
+ {
+ perm[i] = set->first + i;
+ }
+ EGLPNUM_TYPENAME_ILLutil_EGlpNum_perm_quicksort (perm, lp->sos_weight, set->nelem);
+ for (i = 1; i < set->nelem; i++)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqqual
+ (lp->sos_weight[perm[i - 1]], lp->sos_weight[perm[i]]))
+ {
+ c1 = EGLPNUM_TYPENAME_ILLraw_colname (lp, lp->sos_col[perm[i]]);
+ c2 = EGLPNUM_TYPENAME_ILLraw_colname (lp, lp->sos_col[perm[i - 1]]);
+ EGLPNUM_TYPENAME_ILLdata_error (lp->error_collector,
+ "\"%s\" and \"%s\" both have %s %f.\n", c1, c2,
+ "SOS weight", lp->sos_weight[perm[i]]);
+ rval = 1;
+ }
+ }
+ }
+ }
+ }
+ for (i = 0; i < lp->ncols; i++)
+ {
+ ILL_CHECKnull (EGLPNUM_TYPENAME_ILLraw_colname (lp, i), "There is a NULL col name");
+ }
+ for (i = 0; i < lp->nrows; i++)
+ {
+ ILL_CHECKnull (EGLPNUM_TYPENAME_ILLraw_rowname (lp, i), "There is a NULL row name");
+ }
+ ILL_FAILtrue ((lp->upper == NULL) | (lp->lower == NULL),
+ "Upper/Lower arrays must be filled in.");
+
+ rval += ILLraw_check_bounds (lp);
+CLEANUP:
+ ILL_IFFREE (perm, int);
+
+ ILL_RESULT (rval, "ILLcheck_rawlpdata");
+}
+
+int EGLPNUM_TYPENAME_ILLraw_init_bounds (
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+ int i, rval = 0;
+
+ ILL_FAILfalse (lp->upper == NULL, "Should be called exactly once");
+ ILL_FAILfalse (lp->lower == NULL, "Should be called exactly once");
+ ILL_FAILfalse (lp->lbind == NULL, "Should be called exactly once");
+ ILL_FAILfalse (lp->ubind == NULL, "Should be called exactly once");
+ lp->upper = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->ncols);
+ lp->lower = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->ncols);
+ ILL_SAFE_MALLOC (lp->lbind, lp->ncols, char);
+ ILL_SAFE_MALLOC (lp->ubind, lp->ncols, char);
+
+ for (i = 0; i < lp->ncols; i++)
+ {
+ lp->lbind[i] = (char) 0;
+ lp->ubind[i] = (char) 0;
+ EGLPNUM_TYPENAME_EGlpNumZero (lp->lower[i]);
+ }
+CLEANUP:
+ ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLraw_init_bounds");
+}
+
+const char *EGLPNUM_TYPENAME_ILLraw_set_lowerBound (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ int i,
+ EGLPNUM_TYPE bnd)
+{
+ ILL_FAILtrue_no_rval (i >= lp->ncols, "proper colind");
+ if (lp->lbind[i])
+ {
+ return "Using previous bound definition.";
+ }
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->lower[i], bnd);
+ lp->lbind[i] = (char) 1;
+CLEANUP:
+ return NULL;
+}
+
+const char *EGLPNUM_TYPENAME_ILLraw_set_upperBound (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ int i,
+ EGLPNUM_TYPE bnd)
+{
+ ILL_FAILtrue_no_rval (i >= lp->ncols, "proper colind");
+ if (lp->ubind[i])
+ {
+ return "Using previous bound definition.";
+ }
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->upper[i], bnd);
+ lp->ubind[i] = (char) 1;
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (lp->lower[i]) &&
+ !EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (bnd))
+ {
+ return "0.0 upper bound fixes variable.";
+ }
+CLEANUP:
+ return NULL;
+}
+
+const char *EGLPNUM_TYPENAME_ILLraw_set_fixedBound (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ int i,
+ EGLPNUM_TYPE bnd)
+{
+ ILL_FAILtrue_no_rval (i >= lp->ncols, "proper colind");
+ if (lp->ubind[i] || lp->lbind[i])
+ {
+ return "Using previous bound definition.";
+ }
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->lower[i], bnd);
+ lp->lbind[i] = (char) 1;
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->upper[i], bnd);
+ lp->ubind[i] = (char) 1;
+CLEANUP:
+ return NULL;
+}
+
+const char *EGLPNUM_TYPENAME_ILLraw_set_unbound (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ int i)
+{
+ ILL_FAILtrue_no_rval (i >= lp->ncols, "proper colind");
+ if (lp->lbind[i] || lp->ubind[i])
+ {
+ return "Using previous bound definition.";
+ }
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->lower[i], EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->upper[i], EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+ lp->lbind[i] = 1;
+ lp->ubind[i] = 1;
+CLEANUP:
+ return NULL;
+}
+
+const char *EGLPNUM_TYPENAME_ILLraw_set_binaryBound (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ int i)
+{
+ ILL_FAILtrue_no_rval (i >= lp->ncols, "proper colind");
+ if (lp->lbind[i] || lp->ubind[i])
+ {
+ return "Using previous bound definition.";
+ }
+ EGLPNUM_TYPENAME_EGlpNumZero (lp->lower[i]);
+ EGLPNUM_TYPENAME_EGlpNumOne (lp->upper[i]);
+ lp->lbind[i] = 1;
+ lp->ubind[i] = 1;
+CLEANUP:
+ return NULL;
+}
+
+int EGLPNUM_TYPENAME_ILLraw_fill_in_bounds (
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+ int rval = 0, i;
+
+ if (lp->lbind == NULL)
+ {
+ EGLPNUM_TYPENAME_ILLraw_init_bounds (lp);
+ }
+ ILL_FAILtrue (lp->upper == NULL, "must all be there now");
+ ILL_FAILtrue (lp->lower == NULL, "must all be there now");
+ ILL_FAILtrue (lp->lbind == NULL, "must all be there now");
+ ILL_FAILtrue (lp->ubind == NULL, "must all be there now");
+ for (i = 0; i < lp->ncols; i++)
+ {
+ if (!lp->lbind[i])
+ {
+ if (lp->ubind[i] && EGLPNUM_TYPENAME_EGlpNumIsLessZero (lp->upper[i]))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->lower[i], EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+ }
+ }
+ if (!lp->ubind[i])
+ {
+ /* int vars without bounds are binary */
+ /* all, also int vars */
+ /* with explicit lower bound 0.0 are in [0.0,+inf] */
+ if (((lp->intmarker != NULL) && lp->intmarker[i]) && !lp->lbind[i])
+ {
+ EGLPNUM_TYPENAME_EGlpNumOne (lp->upper[i]);
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->upper[i], EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+ }
+ }
+ }
+
+CLEANUP:
+ if (rval)
+ {
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->lower);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->upper);
+ }
+ ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLraw_fill_in_bounds");
+}
+
+static int ILLraw_check_bounds (
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+ int rval = 0, i;
+
+ ILL_FAILtrue (lp->upper == NULL, "must all be there now");
+ ILL_FAILtrue (lp->lower == NULL, "must all be there now");
+ ILL_FAILtrue (lp->lbind == NULL, "must all be there now");
+ ILL_FAILtrue (lp->ubind == NULL, "must all be there now");
+ for (i = 0; i < lp->ncols; i++)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (lp->upper[i], lp->lower[i]))
+ {
+ rval += EGLPNUM_TYPENAME_ILLdata_error (lp->error_collector,
+ "Lower bound is bigger than %s \"%s\".\n",
+ "upper bound for", EGLPNUM_TYPENAME_ILLraw_colname (lp, i));
+ }
+ }
+ ILL_RESULT (rval, "ILLraw_check_bounds");
+CLEANUP:
+ ILL_RETURN (rval, "ILLraw_check_bounds");
+}
+
+int EGLPNUM_TYPENAME_ILLraw_first_nondefault_bound (
+ EGLPNUM_TYPENAME_ILLlpdata * lp)
+{
+ int ri = lp->nstruct, i;
+
+ ILL_FAILtrue_no_rval (lp->lower == NULL || lp->upper == NULL,
+ "Should not call write_bounds when lower or upper are NULL");
+ for (ri = 0; ri < lp->nstruct; ri++)
+ {
+ i = lp->structmap[ri];
+ if (!EGLPNUM_TYPENAME_ILLraw_default_lower (lp, i) || !EGLPNUM_TYPENAME_ILLraw_default_upper (lp, i, ri))
+ break;
+ }
+CLEANUP:
+ return ri;
+}
+
+int EGLPNUM_TYPENAME_ILLraw_default_lower (
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ int i)
+{
+ ILL_FAILtrue_no_rval (lp->lower == NULL || lp->upper == NULL,
+ "Should not call write_bounds when lower or upper are NULL");
+ ILL_FAILfalse_no_rval (lp->ncols > i, "i is not col index");
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (lp->lower[i]) &&
+ !EGLPNUM_TYPENAME_EGlpNumIsLessZero (lp->upper[i]))
+ {
+ return 1;
+ }
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (lp->lower[i], EGLPNUM_TYPENAME_ILL_MINDOUBLE) &&
+ EGLPNUM_TYPENAME_EGlpNumIsLessZero (lp->upper[i]))
+ {
+ return 1;
+ }
+CLEANUP:
+ return 0;
+}
+
+int EGLPNUM_TYPENAME_ILLraw_default_upper (
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ int i,
+ int ri)
+{
+ int isInt;
+
+ ILL_FAILtrue_no_rval (lp->lower == NULL || lp->upper == NULL,
+ "Should not call write_bounds when lower or upper are NULL");
+ ILL_FAILfalse_no_rval (lp->ncols >= i, "i is not col index");
+ isInt = (lp->intmarker != NULL) && lp->intmarker[ri];
+ if (isInt)
+ {
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (lp->lower[i]))
+ {
+ return (EGLPNUM_TYPENAME_EGlpNumIsEqqual (lp->upper[i], EGLPNUM_TYPENAME_oneLpNum));
+ }
+ }
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (lp->upper[i], EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+ {
+ return 1;
+ }
+CLEANUP:
+ return 0;
+}
+
+int EGLPNUM_TYPENAME_ILLraw_fill_in_rownames (
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+ int i, rval = 0;
+ char uname2[ILL_namebufsize];
+ ILLsymboltab *rowtab;
+ char first = 1;
+
+ rowtab = &lp->rowtab;
+ ILL_FAILtrue (lp->nrows != rowtab->tablesize, "must have same #entries");
+ for (i = 0; (rval == 0) && i < lp->nrows; i++)
+ {
+ if (ILLsymboltab_get (rowtab, i) == NULL)
+ {
+ if (first)
+ {
+ EGLPNUM_TYPENAME_ILLdata_warn (lp->error_collector,
+ "Generating names for unnamed rows.");
+ first = 0;
+ }
+
+ ILLsymboltab_unique_name (rowtab, i, "c", uname2);
+ rval = ILLsymboltab_rename (rowtab, i, uname2);
+ ILL_CLEANUP_IF (rval);
+ }
+ }
+CLEANUP:
+ ILL_RESULT (rval, "EGLPNUM_TYPENAME_ILLraw_fill_in_rownames");
+}
+
+static int whichColsAreUsed (
+ EGLPNUM_TYPENAME_rawlpdata * raw,
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ int *colindex)
+{
+ int rval = 0;
+ int i, objind = raw->objindex;
+ EGLPNUM_TYPENAME_colptr *cp;
+ char *colUsed = NULL;
+
+ /* colUsed[i] variable raw->colnames[i] is used in obj fct
+ * and/or equation(s) */
+ ILL_SAFE_MALLOC (colUsed, raw->ncols, char);
+
+ for (i = 0; i < raw->ncols; i++)
+ {
+ colUsed[i] = 0;
+ }
+ for (i = 0; i < raw->ncols; i++)
+ {
+ for (cp = raw->cols[i]; cp; cp = cp->next)
+ {
+ if ((cp->this_val == objind) || (raw->rowsense[cp->this_val] != 'N'))
+ {
+ colUsed[i] = 1;
+ break;
+ }
+ }
+ }
+
+ /* colindex[i] = -1 for undefined, 0, 1, ... lp->ncol-1
+ * lp->ncols <= raw->ncols */
+ for (i = 0; i < raw->ncols; i++)
+ {
+ if (colUsed[i])
+ {
+ colindex[i] = lp->ncols++;
+ }
+ else
+ {
+ colindex[i] = -1;
+ EGLPNUM_TYPENAME_ILLdata_warn (raw->error_collector,
+ "\"%s\" is used in non objective 'N' rows only.",
+ EGLPNUM_TYPENAME_ILLraw_colname (raw, i));
+ }
+ }
+ if (lp->ncols < 1)
+ {
+ rval = EGLPNUM_TYPENAME_ILLdata_error (raw->error_collector, "There are no variables.");
+ ILL_CLEANUP_IF (rval);
+ }
+CLEANUP:
+ ILL_IFFREE (colUsed, char);
+
+ ILL_RESULT (rval, "whichColsAreUsed");
+}
+
+static int whichRowsAreUsed (
+ EGLPNUM_TYPENAME_rawlpdata * raw,
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ int *rowindex)
+{
+ int i, rval = 0;
+
+ /* only use non 'N' rows */
+ for (i = 0; i < raw->nrows; i++)
+ {
+ if (raw->rowsense[i] != 'N')
+ {
+ rowindex[i] = lp->nrows++;
+ }
+ else
+ {
+ rowindex[i] = -1;
+ }
+ }
+ if (lp->nrows == 0)
+ {
+ rval = EGLPNUM_TYPENAME_ILLdata_error (raw->error_collector, "There are no constraints.");
+ }
+ ILL_RESULT (rval, "whichRowsAreUsed");
+}
+
+
+static int transferObjective (
+ EGLPNUM_TYPENAME_rawlpdata * raw,
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ int *colindex)
+{
+ int rval = 0, i, ci, objind = raw->objindex;
+ EGLPNUM_TYPENAME_colptr *cp;
+ int *coefWarn = NULL;
+
+ /* transfer objective fct */
+ lp->obj = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->ncols);
+ ILL_SAFE_MALLOC (coefWarn, lp->ncols, int);
+
+ for (i = 0; i < lp->ncols; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumZero (lp->obj[i]);
+ coefWarn[i] = 0;
+ }
+ for (i = 0; i < raw->ncols; i++)
+ {
+ for (cp = raw->cols[i]; cp; cp = cp->next)
+ {
+ if (cp->this_val == objind)
+ {
+ ci = colindex[i];
+ TESTG ((rval =
+ (ci < 0
+ || ci >= lp->ncols)), CLEANUP, "ci %d is out of range [0,%d[",
+ ci, lp->ncols);
+ ILL_FAILfalse (ci != -1,
+ "all vars in obj fct should be marked as useful");
+ coefWarn[ci]++;
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (cp->coef))
+ EGLPNUM_TYPENAME_EGlpNumAddTo (lp->obj[ci], cp->coef);
+ if (coefWarn[ci] == 2)
+ {
+ EGLPNUM_TYPENAME_ILLdata_warn (raw->error_collector,
+ "Multiple coefficients for \"%s\" in %s.",
+ EGLPNUM_TYPENAME_ILLraw_colname (raw, i), "objective function");
+ }
+ }
+ }
+ }
+CLEANUP:
+ ILL_IFFREE (coefWarn, int);
+
+ ILL_RETURN (rval, "transferObjective");
+}
+
+static int transferColNamesLowerUpperIntMarker (
+ EGLPNUM_TYPENAME_rawlpdata * raw,
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ int *colindex)
+{
+ int i, ci, ind, pre, rval = 0;
+ int hasIntVar;
+ ILL_SAFE_MALLOC (lp->colnames, lp->ncols, char *);
+
+ if (raw->upper)
+ lp->upper = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->ncols);
+ if (raw->lower)
+ lp->lower = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->ncols);
+ ILL_SAFE_MALLOC (lp->intmarker, lp->ncols, char);
+
+ hasIntVar = 0;
+ for (i = 0; i < raw->ncols; i++)
+ {
+ ci = colindex[i];
+ if (ci != -1)
+ {
+ ILL_FAILfalse ((ci >= 0) && (ci < lp->ncols), "colindex problem");
+ ILL_UTIL_STR (lp->colnames[ci], EGLPNUM_TYPENAME_ILLraw_colname (raw, i));
+ rval = ILLsymboltab_register (&lp->coltab,
+ lp->colnames[ci], -1, &ind, &pre);
+ ILL_FAILfalse ((rval == 0) && (ind == ci) && (pre == 0),
+ "should have new entry");
+ if (raw->upper)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->upper[ci], raw->upper[i]);
+ }
+ if (raw->lower)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->lower[ci], raw->lower[i]);
+ }
+ lp->intmarker[ci] = raw->intmarker[i];
+ hasIntVar = hasIntVar || lp->intmarker[ci];
+ ILL_IFDOTRACE
+ {
+ if (lp->lower)
+ {
+ ILLprt_EGlpNum (stdout, &(lp->lower[ci]));
+ ILL_IFTRACE (" <= ");
+ }
+ ILL_IFTRACE ("%s", lp->colnames[ci]);
+ if (lp->upper)
+ {
+ ILL_IFTRACE (" <= ");
+ ILLprt_EGlpNum (stdout, &(lp->upper[ci]));
+ }
+ if (lp->intmarker[ci])
+ {
+ ILL_IFTRACE (" INTEGER ");
+ }
+ ILL_IFTRACE ("\n");
+ }
+ }
+ }
+ if (!hasIntVar)
+ {
+ ILL_IFFREE (lp->intmarker, char);
+ }
+CLEANUP:
+ ILL_RETURN (rval, "transferColNamesLowerUpperIntMarker");
+}
+
+static void safeRegister (
+ ILLsymboltab * tab,
+ const char *name,
+ int i)
+{
+ int ind, pre, rval;
+
+ rval = ILLsymboltab_register (tab, name, -1, &ind, &pre);
+ ILL_FAILfalse ((rval == 0) && (ind == i) && (pre == 0),
+ "Pgming Error: should have new entry");
+CLEANUP:
+ return;
+}
+
+static int transferSenseRhsRowNames (
+ EGLPNUM_TYPENAME_rawlpdata * raw,
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ int *rowindex)
+{
+ int i, ri, rval = 0;
+ int objind = raw->objindex;
+
+ /* transfer sense/rhs/rownames */
+ if (lp->nrows > 0)
+ {
+ ILL_SAFE_MALLOC (lp->sense, lp->nrows, char);
+
+ lp->rhs = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+ ILL_SAFE_MALLOC (lp->rownames, lp->nrows, char *);
+
+ ILL_FAILfalse (EGLPNUM_TYPENAME_ILLraw_rowname (raw, raw->objindex), "NULL objname");
+ safeRegister (&lp->rowtab, EGLPNUM_TYPENAME_ILLraw_rowname (raw, raw->objindex), 0);
+
+ ri = 0;
+ for (i = 0; i < raw->nrows; i++)
+ {
+ ri = rowindex[i];
+ if (i == raw->refrowind)
+ {
+ ILL_UTIL_STR (lp->refrowname, EGLPNUM_TYPENAME_ILLraw_rowname (raw, i));
+ lp->refind = ri;
+ }
+ if (raw->rowsense[i] != 'N')
+ {
+ ILL_FAILfalse (EGLPNUM_TYPENAME_ILLraw_rowname (raw, i) != NULL,
+ "all rownames should be non NULL");
+ ILL_UTIL_STR (lp->rownames[ri], EGLPNUM_TYPENAME_ILLraw_rowname (raw, i));
+ safeRegister (&lp->rowtab, lp->rownames[ri], ri + 1);
+ lp->sense[ri] = raw->rowsense[i];
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->rhs[ri], raw->rhs[i]);
+ }
+ else if (i == objind)
+ {
+ ILL_FAILfalse (lp->objname == NULL, "objname == NULL");
+ ILL_UTIL_STR (lp->objname, EGLPNUM_TYPENAME_ILLraw_rowname (raw, i));
+ }
+ else
+ {
+ /* unused 'N' row */
+ }
+ }
+ ILL_FAILfalse ((lp->nrows + 1) == lp->rowtab.tablesize,
+ "problem with rowtab structure");
+ }
+CLEANUP:
+ ILL_RETURN (rval, "transferSenseRhsRowNames");
+}
+
+static int buildMatrix (
+ EGLPNUM_TYPENAME_rawlpdata * raw,
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ int *rowindex,
+ int *colindex)
+{
+ int i, ri, ci, k, nempty = 0, rval = 0;
+ int *nRowsUsed = 0;
+ int *coefSet = 0;
+ int *coefWarn = 0;
+ EGLPNUM_TYPENAME_ILLmatrix *A = &lp->A;
+ EGLPNUM_TYPENAME_colptr *cp = NULL;
+
+ /* put subjective fcts into matrix */
+ ILL_SAFE_MALLOC (A->matcnt, lp->ncols, int);
+ ILL_SAFE_MALLOC (A->matbeg, lp->ncols, int);
+ ILL_SAFE_MALLOC (nRowsUsed, lp->nrows, int);
+
+ ILL_SAFE_MALLOC (coefWarn, lp->ncols, int);
+
+ for (i = 0; i < lp->ncols; i++)
+ {
+ coefWarn[i] = 0;
+ }
+ for (i = 0; i < lp->nrows; i++)
+ {
+ nRowsUsed[i] = -1;
+ }
+ for (i = 0; i < raw->ncols; i++)
+ {
+ ci = colindex[i];
+ if (ci == -1)
+ continue;
+ k = 0;
+ for (cp = raw->cols[i]; cp; cp = cp->next)
+ {
+ ri = rowindex[cp->this_val];
+ if (ri >= 0)
+ {
+ if (nRowsUsed[ri] != i)
+ {
+ nRowsUsed[ri] = i;
+ k++;
+ }
+ else
+ {
+ if (!coefWarn[ci])
+ {
+ EGLPNUM_TYPENAME_ILLdata_warn (raw->error_collector,
+ "Multiple coefficients for \"%s\" %s.",
+ lp->colnames[i], "in a row");
+ coefWarn[ci] = 1;
+ }
+ }
+ }
+ }
+ A->matcnt[ci] = k;
+ A->matbeg[ci] = lp->nzcount + nempty; /* mark empty cols */
+ lp->nzcount += k;
+ if (k == 0)
+ nempty++;
+ }
+
+ A->matrows = lp->nrows;
+ A->matcols = lp->ncols;
+ A->matcolsize = lp->ncols;
+ A->matsize = lp->nzcount + nempty + 1;
+ A->matfree = 1;
+ ILL_SAFE_MALLOC (A->matind, A->matsize, int);
+
+ A->matval = EGLPNUM_TYPENAME_EGlpNumAllocArray (A->matsize);
+ ILL_SAFE_MALLOC (coefSet, lp->nrows, int);
+
+ for (k = 0; k < lp->nrows; k++)
+ {
+ coefSet[k] = -1;
+ }
+
+ for (i = 0; i < raw->ncols; i++)
+ {
+ ci = colindex[i];
+ if (ci == -1)
+ continue; /* unused variable */
+ k = A->matbeg[ci];
+ if (A->matcnt[ci] == 0)
+ {
+ A->matind[k] = 1; /* Used in addcols and addrows */
+ }
+ else
+ {
+ for (cp = raw->cols[i]; cp; cp = cp->next)
+ {
+ ri = rowindex[cp->this_val];
+ if (ri >= 0)
+ {
+ if (coefSet[ri] == -1)
+ {
+ A->matind[k] = ri;
+ EGLPNUM_TYPENAME_EGlpNumCopy (A->matval[k], cp->coef);
+ coefSet[ri] = k;
+ k++;
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumAddTo (A->matval[coefSet[ri]], cp->coef);
+ }
+ }
+ }
+ if (k != A->matbeg[ci] + A->matcnt[ci])
+ {
+ ILL_ERROR (rval, "problem with matrix");
+ }
+ for (k--; k >= A->matbeg[ci]; k--)
+ {
+ coefSet[A->matind[k]] = -1;
+ }
+ }
+ }
+ A->matind[lp->nzcount + nempty] = -1;
+CLEANUP:
+ ILL_IFFREE (nRowsUsed, int);
+ ILL_IFFREE (coefWarn, int);
+ ILL_IFFREE (coefSet, int);
+
+ ILL_RETURN (rval, "buildMatrix");
+}
+
+static int transferRanges (
+ EGLPNUM_TYPENAME_rawlpdata * raw,
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ int *rowindex)
+{
+ int i, ri, rval = 0;
+ EGLPNUM_TYPENAME_colptr *cp;
+
+ /*****************************************************/
+ /* */
+ /* Interpretation of RANGE values in MPS files */
+ /* */
+ /* G rhs <= row <= rhs + |range| */
+ /* L rhs - |range| <= row <= rhs */
+ /* E + rhs <= row <= rhs + range */
+ /* E - rhs + range <= row <= rhs */
+ /* */
+ /* - where + and - refer to the sign of range */
+ /* and the letters refer to sense of the row. */
+ /* */
+ /* We will store ranged rows as */
+ /* */
+ /* rhs <= row <= rhs + range */
+ /* */
+ /*****************************************************/
+
+
+ lp->rangeval = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+ for (i = 0; i < lp->nrows; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumZero (lp->rangeval[i]);
+ }
+ for (cp = raw->ranges; cp; cp = cp->next)
+ {
+ i = cp->this_val;
+ ri = rowindex[cp->this_val];
+ switch (raw->rowsense[i])
+ {
+ case 'N':
+ EGLPNUM_TYPENAME_ILLdata_error (raw->error_collector, "No range for N-row.\n");
+ rval = 1;
+ goto CLEANUP;
+ case 'G':
+ lp->sense[ri] = 'R';
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs (lp->rangeval[ri], cp->coef);
+ break;
+ case 'L':
+ lp->sense[ri] = 'R';
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs (lp->rangeval[ri], cp->coef);
+ EGLPNUM_TYPENAME_EGlpNumSubTo (lp->rhs[ri], lp->rangeval[ri]);
+ break;
+ case 'E':
+ lp->sense[ri] = 'R';
+ if (!EGLPNUM_TYPENAME_EGlpNumIsLessZero (cp->coef))
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->rangeval[ri], cp->coef);
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumAddTo (lp->rhs[ri], cp->coef);
+ EGLPNUM_TYPENAME_EGlpNumCopyNeg (lp->rangeval[ri], cp->coef);
+ }
+ break;
+ }
+ }
+CLEANUP:
+ ILL_RETURN (rval, "transferRanges");
+}
+
+static int initStructmap (
+ EGLPNUM_TYPENAME_ILLlpdata * lp)
+{
+ int i, rval = 0;
+
+ /* all vars are structural */
+ ILL_SAFE_MALLOC (lp->structmap, lp->nstruct, int);
+
+ for (i = 0; i < lp->nstruct; i++)
+ {
+ lp->structmap[i] = i;
+ }
+
+CLEANUP:
+ ILL_RETURN (rval, "initStructmap");
+}
+
+static int buildSosInfo (
+ EGLPNUM_TYPENAME_rawlpdata * raw,
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ int *colindex)
+{
+ int i, ci, set, rval = 0;
+ int nSosMem, nSetMem;
+
+ /* build sos info */
+ /* see comment in lpdata_EGLPNUM_TYPENAME.h about EGLPNUM_TYPENAME_ILLlpdata's sos and is_sos_mem
+ * fields and section of EGLPNUM_TYPENAME_ILLprint_rawlpdata that prints SOS sets */
+
+ ILL_SAFE_MALLOC (lp->is_sos_mem, lp->ncols, int);
+
+ nSosMem = 0;
+ for (i = 0; i < raw->ncols; i++)
+ {
+ ci = colindex[i];
+ if (ci != -1)
+ {
+ lp->is_sos_mem[ci] = raw->is_sos_member[i];
+ if (raw->is_sos_member[i] != -1)
+ nSosMem++;
+ }
+ }
+ if (nSosMem > 0)
+ {
+ lp->sos.matsize = nSosMem;
+ lp->sos.matcols = raw->nsos;
+ lp->sos.matcolsize = raw->nsos;
+ lp->sos.matrows = lp->ncols;
+ lp->sos.matfree = 0;
+ lp->sos.matval = EGLPNUM_TYPENAME_EGlpNumAllocArray (nSosMem);
+ ILL_SAFE_MALLOC (lp->sos.matind, nSosMem, int);
+ ILL_SAFE_MALLOC (lp->sos.matbeg, raw->nsos, int);
+ ILL_SAFE_MALLOC (lp->sos.matcnt, raw->nsos, int);
+ ILL_SAFE_MALLOC (lp->sos_type, raw->nsos, char);
+
+ nSosMem = 0;
+ for (set = 0; set < raw->nsos; set++)
+ {
+ lp->sos_type[set] = raw->sos_set[set].type;
+ lp->sos.matbeg[set] = nSosMem;
+ nSetMem = 0;
+ for (i = raw->sos_set[set].first;
+ i < raw->sos_set[set].first + raw->sos_set[set].nelem; i++)
+ {
+ ci = colindex[raw->sos_col[i]];
+ if (ci != -1)
+ {
+ lp->sos.matind[nSosMem + nSetMem] = ci;
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->sos.matval[nSosMem + nSetMem], raw->sos_weight[i]);
+ nSetMem++;
+ }
+ }
+ lp->sos.matcnt[set] = nSetMem;
+ nSosMem += nSetMem;
+ }
+ }
+CLEANUP:
+ ILL_RETURN (rval, "buildSosInfo");
+}
+
+static int convert_rawlpdata_to_lpdata (
+ EGLPNUM_TYPENAME_rawlpdata * raw,
+ EGLPNUM_TYPENAME_ILLlpdata * lp)
+/*
+ * only raw's non 'N' rows are converted to matrix entries in lp
+ * columns that are used in non objective 'N' rows only are not
+ * converted. That is they don't end up in lp's matrix, row/colnames,
+ * upper/lower bounds or SOS information.
+ */
+{
+ int rval = 0;
+ int *rowindex = 0;
+ int *colindex = 0;
+
+ ILL_FAILfalse ((raw && lp), "rawlpdata_to_lpdata called without input");
+ if (raw->name == NULL)
+ {
+ EGLPNUM_TYPENAME_ILLdata_warn (raw->error_collector, "Setting problem name to \"unnamed\".");
+ ILL_UTIL_STR (raw->name, "unnamed");
+ }
+ rval = ILLcheck_rawlpdata (raw);
+ ILL_CLEANUP_IF (rval);
+
+ ILL_FAILfalse (raw->objindex != -1, "EGLPNUM_TYPENAME_rawlpdata must have objective fct.");
+ EGLPNUM_TYPENAME_ILLlpdata_init (lp);
+
+ ILL_IFFREE (lp->probname, char);
+
+ lp->probname = raw->name;
+ raw->name = 0;
+
+ /* MINIMIZE or MAXIMIZE ? */
+ lp->objsense = raw->objsense;
+ if (lp->objsense != EGLPNUM_TYPENAME_ILL_MIN && lp->objsense != EGLPNUM_TYPENAME_ILL_MAX)
+ {
+ EGLPNUM_TYPENAME_ILLdata_error (raw->error_collector, "Bad objsense.\n");
+ rval = 1;
+ goto CLEANUP;
+ }
+
+ ILL_SAFE_MALLOC (colindex, raw->ncols, int);
+ ILL_SAFE_MALLOC (rowindex, raw->nrows, int);
+
+ rval = whichColsAreUsed (raw, lp, colindex) ||
+ whichRowsAreUsed (raw, lp, rowindex);
+ ILL_CLEANUP_IF (rval);
+ ILL_FAILtrue (lp->ncols == 0 || lp->nrows == 0, "we need rows and cols");
+
+ /* array sizes */
+ lp->rowsize = lp->nrows;
+ lp->colsize = lp->ncols;
+ lp->nstruct = lp->ncols;
+ lp->structsize = lp->ncols;
+ ILLsymboltab_create (&lp->rowtab, lp->nrows);
+ ILLsymboltab_create (&lp->coltab, lp->ncols);
+
+ rval = transferObjective (raw, lp, colindex);
+ rval = rval || transferColNamesLowerUpperIntMarker (raw, lp, colindex);
+ rval = rval || buildMatrix (raw, lp, rowindex, colindex);
+ rval = rval || buildSosInfo (raw, lp, colindex);
+ ILL_CLEANUP_IF (rval);
+ ILL_IFDOTRACE
+ {
+ EGioFile_t*lout = EGioOpenFILE(stdout);
+ EGLPNUM_TYPENAME_ILLmatrix_prt (lout, &lp->A);
+ EGioClose(lout);
+ }
+
+ rval = transferSenseRhsRowNames (raw, lp, rowindex);
+ if ((lp->nrows > 0) && raw->ranges)
+ {
+ rval = rval || transferRanges (raw, lp, rowindex);
+ }
+ ILL_CLEANUP_IF (rval);
+
+ rval = initStructmap (lp);
+ ILL_CLEANUP_IF (rval);
+
+CLEANUP:
+
+ ILL_IFFREE (rowindex, int);
+ ILL_IFFREE (colindex, int);
+
+ EGLPNUM_TYPENAME_ILLfree_rawlpdata (raw);
+
+ ILL_RESULT (rval, "convert_rawlpdata_to_lpdata");
+}
+
+int EGLPNUM_TYPENAME_ILLrawlpdata_to_lpdata (
+ EGLPNUM_TYPENAME_rawlpdata * raw,
+ EGLPNUM_TYPENAME_ILLlpdata * lp)
+{
+ int rval = 0;
+
+ ILL_IFDOTRACE
+ {
+ QSlog("%s", __func__);
+ EGLPNUM_TYPENAME_ILLprint_rawlpdata (raw);
+ }
+ rval = convert_rawlpdata_to_lpdata (raw, lp);
+ if (rval == 0)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlp_add_logicals (lp);
+ }
+ ILL_RESULT (rval, "EGLPNUM_TYPENAME_ILLrawlpdata_to_lpdata");
+}
+
+static int set_field_name (
+ char **field,
+ const char *name,
+ int *skip)
+{
+ int rval = 0;
+
+ /* name is bounds/rhs/rangesname field from EGLPNUM_TYPENAME_rawlpdata */
+ *skip = 0;
+ if (!*field)
+ {
+ ILL_UTIL_STR (*field, name);
+ }
+
+ if (strcmp (*field, name))
+ {
+ /* not first specified RHS/BOUNDS - skip it */
+ *skip = 1;
+ }
+CLEANUP:
+ ILL_RETURN (rval, "set_field_name");
+}
+
+int EGLPNUM_TYPENAME_ILLraw_set_rhs_name (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ const char *name,
+ int *skip)
+{
+ return set_field_name (&lp->rhsname, name, skip);
+}
+
+int EGLPNUM_TYPENAME_ILLraw_set_bounds_name (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ const char *name,
+ int *skip)
+{
+ return set_field_name (&lp->boundsname, name, skip);
+}
+
+int EGLPNUM_TYPENAME_ILLraw_set_ranges_name (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ const char *name,
+ int *skip)
+{
+ return set_field_name (&lp->rangesname, name, skip);
+}
+
+void EGLPNUM_TYPENAME_ILLprint_rawlpdata (
+ EGLPNUM_TYPENAME_rawlpdata * lp)
+{
+ int i, cnt, si, m;
+ char c;
+ EGLPNUM_TYPE d;
+ EGLPNUM_TYPENAME_colptr *cp;
+ EGLPNUM_TYPENAME_sosptr *set;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (d);
+
+ if (lp)
+ {
+ if (lp->name)
+ {
+ printf ("PROBLEM %s\n", lp->name);
+ }
+ if (lp->rowsense && lp->rhs)
+ {
+ printf ("Subject To\n");
+ for (i = 0; i < lp->nrows; i++)
+ {
+ switch (lp->rowsense[i])
+ {
+ case 'E':
+ c = '=';
+ break;
+ case 'L':
+ c = '<';
+ break;
+ case 'G':
+ c = '>';
+ break;
+ default:
+ c = '?';
+ break;
+ }
+ printf ("%s: %c %f\n", EGLPNUM_TYPENAME_ILLraw_rowname (lp, i), c,
+ EGLPNUM_TYPENAME_EGlpNumToLf (lp->rhs[i]));
+ }
+ printf ("\n");
+ }
+ if (lp->ncols > 0)
+ {
+ printf ("Columns\n");
+ for (i = 0; i < lp->ncols; i++)
+ {
+ for (cp = lp->cols[i]; cp; cp = cp->next)
+ {
+ printf ("%s: ", EGLPNUM_TYPENAME_ILLraw_rowname (lp, cp->this_val));
+ printf ("%c ", (EGLPNUM_TYPENAME_EGlpNumIsLessZero (cp->coef)) ? '-' : '+');
+ EGLPNUM_TYPENAME_EGlpNumCopyAbs (d, cp->coef);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (d, EGLPNUM_TYPENAME_oneLpNum))
+ {
+ printf (" %f ", EGLPNUM_TYPENAME_EGlpNumToLf (d));
+ }
+ printf ("%s\n", EGLPNUM_TYPENAME_ILLraw_colname (lp, i));
+ }
+ printf ("\n");
+ }
+ }
+ if (lp->rangesname)
+ {
+ printf ("RANGES %s\n", lp->rangesname);
+ for (cp = lp->ranges; cp; cp = cp->next)
+ {
+ printf ("(%s, %f) ", EGLPNUM_TYPENAME_ILLraw_rowname (lp, cp->this_val),
+ EGLPNUM_TYPENAME_EGlpNumToLf (cp->coef));
+ }
+ printf ("\n");
+ }
+ if (lp->boundsname)
+ {
+ printf ("BOUNDS %s\n", lp->boundsname);
+ }
+ else
+ {
+ printf ("BOUNDS \n");
+ }
+ if (lp->lower && lp->upper)
+ {
+ for (i = 0; i < lp->ncols; i++)
+ {
+ ILLprt_EGlpNum (stdout, &(lp->lower[i]));
+ printf (" <= %s <= ", EGLPNUM_TYPENAME_ILLraw_colname (lp, i));
+ ILLprt_EGlpNum (stdout, &(lp->upper[i]));
+ printf ("\n");
+ }
+ }
+ if (lp->intmarker)
+ {
+ printf ("Integer\n");
+ cnt = 0;
+ for (i = 0; i < lp->ncols; i++)
+ {
+ if (lp->intmarker[i])
+ {
+ printf ("%s", EGLPNUM_TYPENAME_ILLraw_colname (lp, i));
+ cnt++;
+ if (cnt == 8)
+ {
+ printf ("\n ");
+ cnt = 0;
+ }
+ }
+ }
+ printf ("\n");
+ }
+ printf ("SOS-SETS\n");
+ for (si = 0; si < lp->nsos; si++)
+ {
+ set = lp->sos_set + si;
+ printf ("SOS-SET %d: %s; nelem=%d; first=%d;\n",
+ si, ((set->type == EGLPNUM_TYPENAME_ILL_SOS_TYPE1) ? "TYPE1" : "TYPE2"),
+ set->nelem, set->first);
+ printf ("\t");
+ for (m = set->first; m < set->first + set->nelem; m++)
+ {
+ printf (" %s %f; ", EGLPNUM_TYPENAME_ILLraw_colname (lp, lp->sos_col[m]),
+ EGLPNUM_TYPENAME_EGlpNumToLf (lp->sos_weight[m]));
+ }
+ printf ("\n");
+ }
+ printf ("\n");
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (d);
+}
+
+static int ILLmsg (
+ EGLPNUM_TYPENAME_qserror_collector * collector,
+ int isError,
+ const char *format,
+ va_list args)
+{
+ const char *pre;
+ int slen, errtype;
+ EGLPNUM_TYPENAME_qsformat_error error;
+ char error_desc[256];
+
+ vsprintf (error_desc, format, args);
+ slen = strlen (error_desc);
+ if ((slen > 0) && error_desc[slen - 1] != '\n')
+ {
+ error_desc[slen] = '\n';
+ error_desc[slen + 1] = '\0';
+ }
+
+ if (collector != NULL)
+ {
+ errtype = (isError) ? QS_DATA_ERROR : QS_DATA_WARN;
+ EGLPNUM_TYPENAME_ILLformat_error_create (&error, errtype, error_desc, -1, NULL, -1);
+ EGLPNUM_TYPENAME_ILLformat_error (collector, &error);
+ EGLPNUM_TYPENAME_ILLformat_error_delete (&error);
+ }
+ else
+ {
+ pre = (isError) ? "Data Error" : "Data Warning";
+ QSlog("%s: %s", pre, error_desc);
+ }
+ return 1;
+}
+
+int EGLPNUM_TYPENAME_ILLdata_error (
+ EGLPNUM_TYPENAME_qserror_collector * collector,
+ const char *format,
+ ...)
+{
+ va_list args;
+
+ va_start (args, format);
+ return ILLmsg (collector, TRUE, format, args);
+}
+
+void EGLPNUM_TYPENAME_ILLdata_warn (
+ EGLPNUM_TYPENAME_qserror_collector * collector,
+ const char *format,
+ ...)
+{
+ va_list args;
+
+ va_start (args, format);
+ (void) ILLmsg (collector, FALSE, format, args);
+}
+
+EGLPNUM_TYPENAME_colptr *EGLPNUM_TYPENAME_ILLcolptralloc (
+ ILLptrworld * p)
+{
+ EGLPNUM_TYPENAME_colptr *sol = colptralloc (p);
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar ((sol->coef));
+ return sol;
+}
diff --git a/qsopt_ex/rawlp.h b/qsopt_ex/rawlp.h
new file mode 100644
index 0000000..c701731
--- /dev/null
+++ b/qsopt_ex/rawlp.h
@@ -0,0 +1,259 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: rawlp_EGLPNUM_TYPENAME.h,v $ $Revision: 1.3 $ $Date: 2003/11/05 16:57:39 $"; */
+#ifndef EGLPNUM_TYPENAME___ILL_RAWLP_H_
+#define EGLPNUM_TYPENAME___ILL_RAWLP_H_
+
+/****************************************************************************/
+/* DataStructure and Routines */
+/* to deal with raw lp information as read from mps or lp files */
+/* support scanning of input */
+/* error reporting */
+/****************************************************************************/
+
+#include "allocrus.h"
+#include "eg_lpnum.h"
+#include "symtab.h"
+#include "trace.h"
+
+#include "lpdata_EGLPNUM_TYPENAME.h"
+#include "format_EGLPNUM_TYPENAME.h"
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+
+#define EGLPNUM_TYPENAME_ILL_ISBLANK(p) \
+ (((*(p))==' '||(*(p))=='\t'||(*(p))=='\r'||(*(p))=='\f') ? 1 : 0)
+
+/*
+ * we rely on ILLsymboltab property:
+ * the ith name added can be retrieved by ILLsymboltab_get(table, i)
+ * as long as we never delete names from the symbol table
+ */
+typedef struct EGLPNUM_TYPENAME_rawlpdata
+{
+ char *name;
+
+ char *rhsname;
+ char *rangesname;
+ char *boundsname;
+
+ int objsense; /* maximize or minimize */
+ int objindex; /* index of objective row */
+
+ int nrows; /* number of rows in problem */
+ ILLsymboltab rowtab; /* ILLsymboltab_get(rowtab, i) name of ith row */
+
+ int sensesize; /* size of rowsense */
+ char *rowsense; /* rowsense[i] snese of row[i] */
+
+ char *rhsind; /* rhsind[i] == 1 we saw an rhs for row[i] */
+ /* size is nrows */
+ int rhssize; /* size of rhs array */
+ EGLPNUM_TYPE *rhs; /* rhs values for rows; size is nrows */
+ char *rangesind; /* ranges[i] == 1 we saw a range def for row[i] */
+ struct EGLPNUM_TYPENAME_colptr *ranges; /* list of range values */
+
+ int ncols; /* number of cols in problem */
+ ILLsymboltab coltab; /* ILLsymboltab_get(coltab, i) name of ith col */
+ int colsize; /* size of cols array */
+ struct EGLPNUM_TYPENAME_colptr **cols;
+
+ char *lbind; /* lbind[i] == 1 we saw a lower bound for col[i] */
+ char *ubind; /* ubind[i] == 1 we saw a upper bound for col[i] */
+ EGLPNUM_TYPE *lower; /* lower[i] = lower bound for col[i] */
+ EGLPNUM_TYPE *upper; /* upper[i] = upper bound for col[i] */
+
+ int intsize; /* size of intmarker array */
+ char *intmarker; /* intmarker[i] == 1 col[i] is an int var */
+
+ /* sos information is tranfered into EGLPNUM_TYPENAME_ILLmatrix lpdata->sos */
+ char *refrow; /* name of reference row */
+ int refrowind; /* index of refrow or -1 */
+
+ int is_sos_size; /* size of is_sos_member array */
+ int *is_sos_member; /* for each col contains either
+ * -1 == no sos memeber
+ * i == member of set #i */
+
+ int nsos_member; /* total number of sos set members */
+ int sos_weight_size; /* size of sos_weight array */
+ EGLPNUM_TYPE *sos_weight; /* sos set elem i has weight of sos_weight[i]
+ * value comes from refrow coeficients */
+ int sos_col_size; /* size of sos_col array */
+ int *sos_col; /* sos elem i is column sos_col[i] */
+
+ int nsos; /* number of sos sets */
+ int sos_setsize; /* size of sosset array */
+ struct EGLPNUM_TYPENAME_sosptr *sos_set; /* type, size, first element of sos sets
+ * first is index into sos_weight and sos_col
+ * arrays */
+ EGLPNUM_TYPENAME_qserror_collector *error_collector;
+ ILLptrworld ptrworld;
+}
+EGLPNUM_TYPENAME_rawlpdata;
+
+typedef struct EGLPNUM_TYPENAME_colptr
+{
+ EGLPNUM_TYPE coef;
+ struct EGLPNUM_TYPENAME_colptr *next;
+ int this_val; /* row index */
+}
+EGLPNUM_TYPENAME_colptr;
+extern EGLPNUM_TYPENAME_colptr *EGLPNUM_TYPENAME_ILLcolptralloc (
+ ILLptrworld * p);
+
+typedef struct EGLPNUM_TYPENAME_sosptr
+{
+ int nelem; /* number of set elements */
+ int first; /* index of first set element in sosmemeber */
+ char type; /* set type */
+}
+EGLPNUM_TYPENAME_sosptr;
+extern const int EGLPNUM_TYPENAME_ILL_SOS_TYPE1;
+extern const int EGLPNUM_TYPENAME_ILL_SOS_TYPE2;
+
+extern void EGLPNUM_TYPENAME_ILLinit_rawlpdata (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ EGLPNUM_TYPENAME_qserror_collector * collector);
+extern void EGLPNUM_TYPENAME_ILLfree_rawlpdata (
+ EGLPNUM_TYPENAME_rawlpdata * lp);
+extern void EGLPNUM_TYPENAME_ILLraw_clear_matrix (
+ EGLPNUM_TYPENAME_rawlpdata * lp);
+
+extern const char *EGLPNUM_TYPENAME_ILLraw_rowname (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ int i);
+extern const char *EGLPNUM_TYPENAME_ILLraw_colname (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ int i);
+
+extern int EGLPNUM_TYPENAME_ILLraw_add_col (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ const char *name,
+ int intmarker);
+extern int EGLPNUM_TYPENAME_ILLraw_add_row (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ const char *name,
+ int sense,
+ const EGLPNUM_TYPE rhs);
+
+extern int EGLPNUM_TYPENAME_ILLraw_add_col_coef (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ int colind,
+ int rowind,
+ EGLPNUM_TYPE coef);
+
+extern int EGLPNUM_TYPENAME_ILLraw_init_ranges (
+ EGLPNUM_TYPENAME_rawlpdata * lp);
+extern int EGLPNUM_TYPENAME_ILLraw_init_rhs (
+ EGLPNUM_TYPENAME_rawlpdata * lp);
+
+extern int EGLPNUM_TYPENAME_ILLraw_add_ranges_coef (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ int rowind,
+ EGLPNUM_TYPE coef);
+
+
+extern int EGLPNUM_TYPENAME_ILLraw_add_sos (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ int sos_type);
+
+ /* add empty set with type */
+extern int EGLPNUM_TYPENAME_ILLraw_add_sos_member (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ int colind);
+
+ /* add col to last set */
+extern int EGLPNUM_TYPENAME_ILLraw_is_mem_other_sos (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ int colind);
+
+extern int EGLPNUM_TYPENAME_ILLraw_set_rhs_name (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ const char *name,
+ int *skip);
+extern int EGLPNUM_TYPENAME_ILLraw_set_bounds_name (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ const char *name,
+ int *skip);
+extern int EGLPNUM_TYPENAME_ILLraw_set_ranges_name (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ const char *name,
+ int *skip);
+extern void EGLPNUM_TYPENAME_ILLprint_rawlpdata (
+ EGLPNUM_TYPENAME_rawlpdata * lp);
+
+extern char *EGLPNUM_TYPENAME_ILLraw_unique_name (
+ ILLsymboltab * tab,
+ char *prefix,
+ int i);
+extern int EGLPNUM_TYPENAME_ILLraw_fill_in_rownames (
+ EGLPNUM_TYPENAME_rawlpdata * lp);
+
+extern int EGLPNUM_TYPENAME_ILLraw_init_bounds (
+ EGLPNUM_TYPENAME_rawlpdata * lp);
+
+extern const char *EGLPNUM_TYPENAME_ILLraw_set_lowerBound (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ int i,
+ EGLPNUM_TYPE bnd);
+extern const char *EGLPNUM_TYPENAME_ILLraw_set_upperBound (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ int i,
+ EGLPNUM_TYPE bnd);
+extern const char *EGLPNUM_TYPENAME_ILLraw_set_fixedBound (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ int i,
+ EGLPNUM_TYPE bnd);
+extern const char *EGLPNUM_TYPENAME_ILLraw_set_binaryBound (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ int i);
+extern const char *EGLPNUM_TYPENAME_ILLraw_set_unbound (
+ EGLPNUM_TYPENAME_rawlpdata * lp,
+ int colind);
+extern int EGLPNUM_TYPENAME_ILLraw_fill_in_bounds (
+ EGLPNUM_TYPENAME_rawlpdata * lp);
+
+extern int EGLPNUM_TYPENAME_ILLraw_first_nondefault_bound (
+ EGLPNUM_TYPENAME_ILLlpdata * lp);
+extern int EGLPNUM_TYPENAME_ILLraw_default_lower (
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ int i);
+extern int EGLPNUM_TYPENAME_ILLraw_default_upper (
+ EGLPNUM_TYPENAME_ILLlpdata * lp,
+ int i,
+ int ri);
+
+extern int EGLPNUM_TYPENAME_ILLrawlpdata_to_lpdata (
+ EGLPNUM_TYPENAME_rawlpdata * raw,
+ EGLPNUM_TYPENAME_ILLlpdata * lp);
+
+extern int EGLPNUM_TYPENAME_ILLdata_error (
+ EGLPNUM_TYPENAME_qserror_collector * collector,
+ const char *format,
+ ...);
+extern void EGLPNUM_TYPENAME_ILLdata_warn (
+ EGLPNUM_TYPENAME_qserror_collector * collector,
+ const char *format,
+ ...);
+
+#endif
diff --git a/qsopt_ex/read_lp.c b/qsopt_ex/read_lp.c
new file mode 100644
index 0000000..fd25715
--- /dev/null
+++ b/qsopt_ex/read_lp.c
@@ -0,0 +1,837 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: read_lp_state.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+
+/****************************************************************************/
+/* */
+/* Routines to support Reading LP Files */
+/* */
+/****************************************************************************/
+
+/*
+ * -) anything after '\' is comment
+ * -) variables consist of a-z A-Z 0-9!"#$%(),;.?@_`'{}|~
+ * don't start with a digit or '.'
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "eg_lpnum.h"
+#include "eg_io.h"
+#include "except.h"
+
+#include "read_lp_EGLPNUM_TYPENAME.h"
+#include "lp_EGLPNUM_TYPENAME.h"
+#include "rawlp_EGLPNUM_TYPENAME.h"
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+#include "format_EGLPNUM_TYPENAME.h"
+
+
+static int TRACE = 0;
+
+#define END_LINE(p) (((*p) == '\\' || (*p) == '\n' || (*p) == '\0') ? 1 : 0)
+
+static const char *all_keyword[] = {
+ "MIN", "MINIMUM", "MINIMIZE",
+ "MAX", "MAXIMUM", "MAXIMIZE",
+ "SUBJECT", "ST", "PROBLEM", "PROB",
+ "BOUNDS", "BOUND", "INTEGER", "END", NULL
+};
+static int all_keyword_len[] = {
+ 3, 7, 8,
+ 3, 7, 8,
+ 7, 2, 7, 4,
+ 6, 5, 7, 3, -1
+};
+
+int EGLPNUM_TYPENAME_ILLread_lp_state_init (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ EGLPNUM_TYPENAME_qsline_reader * file,
+ const char *fname,
+ int inter)
+{
+ int rval = 0;
+
+ ILL_FAILtrue (file == NULL, "need a file");
+ state->eof = 0;
+ state->file_name = fname;
+ state->interactive = inter;
+ state->file = file;
+ state->line_num = 0;
+ state->p = state->line;
+ state->line[0] = '\0';
+ state->realline[0] = '\0';
+ state->field[0] = '\0';
+ state->fieldOnFirstCol = 0;
+ EGLPNUM_TYPENAME_EGlpNumInitVar (state->bound_val);
+ EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (state, 1);
+CLEANUP:
+ ILL_RETURN (rval, "EGLPNUM_TYPENAME_ILLread_lp_state_init");
+}
+
+int EGLPNUM_TYPENAME_ILLread_lp_state_next_line (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+ char *slash;
+
+ if (state->eof)
+ {
+ return 1;
+ }
+ state->line[0] = '\0';
+ if (state->interactive)
+ {
+ fprintf (stdout, "> ");
+ fflush (stdout);
+ }
+ while (EGLPNUM_TYPENAME_ILLline_reader_get (state->realline, ILL_namebufsize - 2, state->file)
+ != (char *) NULL)
+ {
+ state->p = state->line;
+ state->line_num++;
+ strcpy (state->line, state->realline);
+ slash = strchr (state->line, '\\');
+ if (slash != NULL)
+ {
+ *slash = '\0';
+ }
+ while (EGLPNUM_TYPENAME_ILL_ISBLANK (state->p))
+ {
+ state->p++;
+ }
+ if (!END_LINE (state->p))
+ {
+ ILL_IFTRACE ("NEWLINE %s %d: %s",
+ state->file_name, state->line_num, state->line);
+ return 0;
+ }
+ if (state->interactive)
+ {
+ fprintf (stdout, "> ");
+ fflush (stdout);
+ }
+ }
+ state->eof = 1;
+ state->line_num++;
+ state->field[0] = '\0';
+ state->line[0] = '\0';
+ strcpy (state->realline, "\n");
+ state->p = state->line;
+ state->fieldOnFirstCol = 0;
+ return 1;
+}
+
+int EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ int wrapLines)
+{
+ while (1)
+ {
+ while (EGLPNUM_TYPENAME_ILL_ISBLANK (state->p))
+ {
+ state->p++;
+ }
+ if (END_LINE (state->p))
+ {
+ if (wrapLines)
+ {
+ if (EGLPNUM_TYPENAME_ILLread_lp_state_next_line (state) != 0)
+ {
+ return 1;
+ }
+ }
+ else
+ {
+ return 0; /* done */
+ }
+ }
+ else
+ {
+ return 0; /* foud non blank */
+ }
+ }
+}
+
+static int next_field (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ int acrossLines)
+{
+ (void) EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (state, (char) acrossLines);
+ if (state->eof)
+ {
+ return 1;
+ }
+ state->fieldOnFirstCol = (state->line == state->p);
+ if (sscanf (state->p, "%s", state->field) != EOF)
+ {
+ state->p += strlen (state->field);
+ return 0;
+ }
+ return 1;
+}
+
+int EGLPNUM_TYPENAME_ILLread_lp_state_next_field_on_line (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+ return next_field (state, 0);
+}
+
+int EGLPNUM_TYPENAME_ILLread_lp_state_next_field (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+ return next_field (state, 1);
+}
+
+void EGLPNUM_TYPENAME_ILLread_lp_state_prev_field (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+ if (state->p > state->line)
+ {
+ state->p--;
+ }
+ while (EGLPNUM_TYPENAME_ILL_ISBLANK (state->p) && (state->p > state->line))
+ {
+ state->p--;
+ }
+ while (!EGLPNUM_TYPENAME_ILL_ISBLANK (state->p) && (state->p > state->line))
+ {
+ state->p--;
+ }
+ state->fieldOnFirstCol = (state->line == state->p);
+}
+
+int EGLPNUM_TYPENAME_ILLread_lp_state_next_var (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+ char *p;
+ int var_len, i;
+
+ if (EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (state, 1))
+ {
+ return 1;
+ }
+ state->fieldOnFirstCol = (state->line == state->p);
+ var_len = 0;
+ p = state->p;
+ while (1)
+ {
+ if (EGLPNUM_TYPENAME_ILLis_lp_name_char (*p, var_len))
+ {
+ p++;
+ var_len++;
+ }
+ else
+ {
+ break;
+ }
+ }
+ if (var_len == 0)
+ {
+ return 1;
+ }
+ if (state->fieldOnFirstCol)
+ {
+ /* see whether we founbd a reserved keyword */
+ for (i = 0; all_keyword[i] != NULL; i++)
+ {
+ if ((var_len == all_keyword_len[i]) &&
+ (strncasecmp (all_keyword[i], state->p, (size_t) (all_keyword_len[i]))
+ == 0))
+ {
+ return -1; /* yes we did */
+ }
+ }
+ }
+ strncpy (state->field, state->p, (size_t) var_len);
+ state->field[var_len] = '\0';
+ state->p = p;
+ return 0;
+}
+
+int EGLPNUM_TYPENAME_ILLread_lp_state_bad_keyword (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+ if (!state->fieldOnFirstCol)
+ {
+ return EGLPNUM_TYPENAME_ILLlp_error (state,
+ "Keyword \"%s\" not at beginning of line.\n",
+ state->field);
+ }
+ return 0;
+}
+
+int EGLPNUM_TYPENAME_ILLtest_lp_state_keyword (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ const char *kwd[])
+{
+ int i = 0;
+
+ if (!state->eof && state->fieldOnFirstCol)
+ {
+ for (i = 0; kwd[i] != NULL; i++)
+ {
+ if (strcasecmp (state->field, kwd[i]) == 0)
+ {
+ return 0;
+ }
+ }
+ }
+ return 1;
+}
+
+int EGLPNUM_TYPENAME_ILLread_lp_state_keyword (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ const char *kwd[])
+{
+ if (state->eof || EGLPNUM_TYPENAME_ILLread_lp_state_bad_keyword (state))
+ {
+ return 1;
+ }
+ return EGLPNUM_TYPENAME_ILLtest_lp_state_keyword (state, kwd);
+}
+
+
+int EGLPNUM_TYPENAME_ILLread_lp_state_colon (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+ if ((EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (state, 1) == 0) && (*state->p == ':'))
+ {
+ state->p++;
+ return 0;
+ }
+ return 1;
+}
+
+int EGLPNUM_TYPENAME_ILLread_lp_state_has_colon (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+ char *pp;
+
+ EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (state, 0);
+ for (pp = state->p; *pp != '\n'; pp++)
+ {
+ if (*pp == ':')
+ {
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int EGLPNUM_TYPENAME_ILLread_lp_state_next_constraint (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+ int rval;
+ int ln = state->line_num;
+
+ EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (state, 1);
+ if (state->eof)
+ {
+ return 1;
+ }
+ if (ln == state->line_num)
+ {
+ return EGLPNUM_TYPENAME_ILLlp_error (state, "Constraints must start on a new line.\n");
+ }
+ if (EGLPNUM_TYPENAME_ILLread_lp_state_next_field (state) == 0)
+ {
+ rval = EGLPNUM_TYPENAME_ILLtest_lp_state_keyword (state, all_keyword);
+ EGLPNUM_TYPENAME_ILLread_lp_state_prev_field (state);
+ return !rval;
+ }
+ return 0;
+}
+
+/* return 0 if there is a sign */
+int EGLPNUM_TYPENAME_ILLread_lp_state_sign (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ EGLPNUM_TYPE * sign)
+{
+ char found = 0;
+
+ EGLPNUM_TYPENAME_EGlpNumOne (*sign);
+ if (EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (state, 1) == 0)
+ {
+ if ((*state->p == '+') || (*state->p == '-'))
+ {
+ if (*state->p != '+')
+ EGLPNUM_TYPENAME_EGlpNumSign (*sign);
+ state->p++;
+ found = 1;
+ }
+ }
+ return 1 - found;
+}
+
+int EGLPNUM_TYPENAME_ILLtest_lp_state_next_is (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ const char *str)
+{
+ EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (state, 0);
+ if (strncasecmp (state->p, str, strlen (str)) == 0)
+ {
+ state->p += strlen (str);
+ return 1;
+ }
+ return 0;
+}
+
+int EGLPNUM_TYPENAME_ILLread_lp_state_value (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ EGLPNUM_TYPE * coef)
+{
+ int len = 0;
+
+ if (EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (state, 1) != 0)
+ {
+ ILL_RESULT (1, "EGLPNUM_TYPENAME_ILLread_lp_state_value");
+ }
+ else
+ {
+ state->fieldOnFirstCol = (state->line == state->p);
+ len = EGLPNUM_TYPENAME_ILLget_value (state->p, coef);
+ if (len > 0)
+ {
+ state->p += len;
+ ILL_RESULT (0, "EGLPNUM_TYPENAME_ILLread_lp_state_value");
+ }
+ ILL_RESULT (1, "EGLPNUM_TYPENAME_ILLread_lp_state_value");
+ }
+}
+
+int EGLPNUM_TYPENAME_ILLread_lp_state_possible_coef (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ EGLPNUM_TYPE * coef,
+ const EGLPNUM_TYPE defValue)
+{
+ EGLPNUM_TYPENAME_EGlpNumCopy (*coef, defValue);
+ return EGLPNUM_TYPENAME_ILLread_lp_state_value (state, coef);
+}
+
+
+int EGLPNUM_TYPENAME_ILLread_lp_state_possible_bound_value (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+ EGLPNUM_TYPE sign;
+ int len = 0;
+ char *p = NULL;
+ int rval = 0;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (sign);
+ (void) EGLPNUM_TYPENAME_ILLread_lp_state_sign (state, &sign);
+
+ if (!strncasecmp (state->p, "INFINITY", (size_t) 8))
+ {
+ len = 8;
+ }
+ else
+ {
+ if (!strncasecmp (state->p, "INF", (size_t) 3))
+ {
+ len = 3;
+ }
+ }
+ if (len > 0)
+ {
+ state->p += len;
+ p = state->p;
+ EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (state, 0);
+ if (!END_LINE (p) && p == state->p)
+ {
+ /* found no blanks so this INF/INFINITY is the prefix
+ * of something else */
+ state->p -= len;
+ goto CLEANUP;
+ return 0; /* no coef found */
+ }
+ else
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (sign))
+ EGLPNUM_TYPENAME_EGlpNumCopy (state->bound_val, EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+ else if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (sign))
+ EGLPNUM_TYPENAME_EGlpNumCopy (state->bound_val, EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+ else
+ EGLPNUM_TYPENAME_EGlpNumZero (state->bound_val);
+ rval = 1;
+ goto CLEANUP;
+ }
+ }
+ if (EGLPNUM_TYPENAME_ILLread_lp_state_value (state, &(state->bound_val)) == 0)
+ {
+ EGLPNUM_TYPENAME_EGlpNumMultTo (state->bound_val, sign);
+ rval = 1;
+ goto CLEANUP;
+ }
+CLEANUP:
+ EGLPNUM_TYPENAME_EGlpNumClearVar (sign);
+ return rval; /* no coef found */
+}
+
+int EGLPNUM_TYPENAME_ILLtest_lp_state_sense (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ int all)
+{
+ char c;
+
+ state->sense_val = ' ';
+ if (EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (state, 1) == 0)
+ {
+ c = *state->p;
+ if (!all)
+ { /* look for '=' and '<=' */
+ if (c == '=')
+ {
+ state->p++;
+ state->sense_val = 'E';
+ }
+ else
+ {
+ if ((c == '<') && (*(state->p + 1) == '='))
+ {
+ state->p += 2;
+ state->sense_val = 'L';
+ }
+ }
+ }
+ else
+ {
+ c = *state->p;
+ if ((c == '<') || (c == '>'))
+ {
+ state->sense_val = (c == '<') ? 'L' : 'G';
+ state->p++;
+ c = *state->p;
+ if (*state->p == '=')
+ {
+ state->p++;
+ }
+ }
+ else
+ {
+ if (c == '=')
+ {
+ state->p++;
+ c = *state->p;
+ if ((c == '<') || (c == '>'))
+ {
+ state->sense_val = (c == '<') ? 'L' : 'G';
+ state->p++;
+ }
+ else
+ {
+ state->sense_val = 'E';
+ }
+ }
+ }
+ }
+ }
+ return (state->sense_val != ' ');
+}
+
+void EGLPNUM_TYPENAME_ILLtest_lp_state_bound_sense (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+ (void) EGLPNUM_TYPENAME_ILLtest_lp_state_sense (state, 0);
+}
+
+int EGLPNUM_TYPENAME_ILLread_lp_state_sense (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+ if (!EGLPNUM_TYPENAME_ILLtest_lp_state_sense (state, 1))
+ {
+ if (END_LINE (state->p))
+ {
+ return EGLPNUM_TYPENAME_ILLlp_error (state, "Missing row sense at end of line.\n");
+ }
+ else
+ {
+ if (*state->p != '\0')
+ {
+ return EGLPNUM_TYPENAME_ILLlp_error (state, "\"%c\" is not a row sense.\n", *state->p);
+ }
+ else
+ {
+ return EGLPNUM_TYPENAME_ILLlp_error (state, "Missing row sense at end of line.\n");
+ }
+ }
+ }
+ return 0;
+}
+
+/* ------------------------------------------------------------------------- */
+/* error printing
+ */
+
+static void ILLread_lp_state_print_at (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+ char *p;
+
+ if (state->eof)
+ {
+ QSlog("end of file");
+ }
+ else
+ {
+ if (*state->p == '\n')
+ {
+ QSlog("end of line");
+ }
+ else
+ {
+ p = state->p;
+ while (EGLPNUM_TYPENAME_ILL_ISBLANK (p))
+ {
+ p++;
+ }
+ QSlog("%c", '"');
+ for (; !EGLPNUM_TYPENAME_ILL_ISBLANK (p) && !END_LINE (p); p++)
+ {
+ QSlog("%c", *p);
+ }
+ QSlog("\"");
+ }
+ }
+}
+
+static void lp_err (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ int isError,
+ const char *format,
+ va_list args)
+{
+ int rval = 0;
+ int errtype, slen, at;
+ EGLPNUM_TYPENAME_qsformat_error error;
+ char error_desc[256];
+
+ ILL_FAILfalse (state != NULL, "state != NULL");
+ ILL_FAILfalse (state->file != NULL, "state->file != NULL");
+ ILL_FAILfalse (format != NULL, "format != NULL");
+ ILL_FAILfalse (format[0] != '\0', "format[0] != '0'");
+
+ EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (state, 0);
+ at = state->p - state->line;
+ vsprintf (error_desc, format, args);
+ slen = strlen (error_desc);
+ if ((slen > 0) && error_desc[slen - 1] != '\n')
+ {
+ error_desc[slen] = '\n';
+ error_desc[slen + 1] = '\0';
+ }
+
+ if (state->file->error_collector != NULL)
+ {
+ errtype = (isError) ? QS_LP_FORMAT_ERROR : QS_LP_FORMAT_WARN;
+ EGLPNUM_TYPENAME_ILLformat_error_create (&error, errtype, error_desc,
+ state->line_num, state->realline, at);
+ EGLPNUM_TYPENAME_ILLformat_error (state->file->error_collector, &error);
+ EGLPNUM_TYPENAME_ILLformat_error_delete (&error);
+ }
+ else
+ {
+ if (!state->interactive)
+ {
+ QSlog("%s %d: %s\t", state->file_name, state->line_num,
+ state->realline);
+ QSlog("%s at ", (isError) ? "LP Error" : "LP Warning");
+ ILLread_lp_state_print_at (state);
+ QSlog(": ");
+ }
+ else
+ {
+ QSlog("%s : ", (isError) ? "LP Error" : "LP Warning");
+ }
+ QSlog("%s", error_desc);
+ }
+CLEANUP:;
+}
+
+int EGLPNUM_TYPENAME_ILLlp_error (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ const char *format,
+ ...)
+{
+ va_list args;
+
+ va_start (args, format);
+ lp_err (state, TRUE, format, args);
+ return 1;
+}
+
+void EGLPNUM_TYPENAME_ILLlp_warn (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ const char *format,
+ ...)
+{
+ va_list args;
+
+ va_start (args, format);
+ if (format != NULL)
+ {
+ lp_err (state, FALSE, format, args);
+ }
+}
+
+/* shared with read_mps_state.c */
+int EGLPNUM_TYPENAME_ILLget_value (
+ char *line,
+ EGLPNUM_TYPE * coef)
+{
+#ifdef mpq_READ_LP_STATE_H
+ mpq_t res;
+ int rval = 0;
+
+ mpq_init (res);
+ rval = mpq_EGlpNumReadStrXc (res, line);
+ if (rval == 0)
+ mpq_set_ui (*coef, 1UL, 1UL);
+ else
+ mpq_set (*coef, res);
+ mpq_clear (res);
+ return rval;
+ //return mpq_EGlpNumReadStrXc (*coef, line);
+#else
+ char field[ILL_namebufsize];
+ int rval = 0, i;
+ char c, lastC, *p;
+ int allowDot, allowExp, allowSign;
+ double dtmp;
+
+ p = line;
+ c = *p;
+ i = 0;
+ lastC = ' ';
+ allowSign = 1;
+ allowExp = 0;
+ allowDot = 1;
+ while ((('0' <= c) && (c <= '9')) ||
+ (allowDot && (c == '.')) ||
+ ((allowExp == 1) && ((c == 'e') || (c == 'E'))) ||
+ ((allowSign || lastC == 'e' || lastC == 'E') &&
+ ((c == '+') || (c == '-'))))
+ {
+ if (c == '.')
+ allowDot = 0;
+ allowSign = 0;
+
+ if ((allowExp == 0) && (c >= '0') && (c <= '9'))
+ {
+ allowExp = 1;
+ }
+ if ((c == 'e') || (c == 'E'))
+ {
+ allowExp++;
+ allowDot = 0;
+ }
+ p++;
+ lastC = c;
+ c = *p;
+ i++;
+ }
+ if ((lastC == '+') || (lastC == '-'))
+ {
+ p--;
+ i--;
+ if (p > line)
+ lastC = *(p - 1);
+ else
+ lastC = ' ';
+ }
+ if ((lastC == 'e') || (lastC == 'E'))
+ {
+ p--;
+ i--;
+ }
+ if (i > 0)
+ {
+ strncpy (field, line, (size_t) i);
+ field[i] = '\0';
+ rval = !sscanf (field, "%lf%n", &dtmp, &i);
+ EGLPNUM_TYPENAME_EGlpNumSet (*coef, dtmp);
+ ILL_IFTRACE ("%la\n", EGLPNUM_TYPENAME_EGlpNumToLf (*coef));
+ if (rval != 0)
+ {
+ ILL_RESULT (0, "EGLPNUM_TYPENAME_ILLget_value");
+ }
+ }
+ //ILL_RESULT (i, "EGLPNUM_TYPENAME_ILLget_value");
+ return i;
+#endif
+}
+
+int EGLPNUM_TYPENAME_ILLcheck_subject_to (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state)
+{
+ int rval;
+ char *p;
+
+ if ((rval = EGLPNUM_TYPENAME_ILLread_lp_state_next_field (state)) == 0)
+ {
+ if (strcasecmp (state->field, "ST") == 0)
+ {
+ rval = EGLPNUM_TYPENAME_ILLread_lp_state_bad_keyword (state);
+ }
+ else
+ {
+ if (strcasecmp (state->field, "SUBJECT") == 0)
+ {
+ p = state->p;
+ while (EGLPNUM_TYPENAME_ILL_ISBLANK (p))
+ {
+ p++;
+ }
+ if (!strncasecmp (p, "TO", (size_t) 2))
+ {
+ rval = EGLPNUM_TYPENAME_ILLread_lp_state_bad_keyword (state);
+ if (rval == 0)
+ {
+ state->p = p + 2;
+ }
+ }
+ }
+ else
+ {
+ rval = 1;
+ }
+ }
+ if (rval != 0)
+ {
+ EGLPNUM_TYPENAME_ILLread_lp_state_prev_field (state);
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (state, 1);
+ }
+ }
+ ILL_RESULT (rval, "check_subject_to");
+}
diff --git a/qsopt_ex/read_lp.h b/qsopt_ex/read_lp.h
new file mode 100644
index 0000000..9750b78
--- /dev/null
+++ b/qsopt_ex/read_lp.h
@@ -0,0 +1,148 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: read_lp_state.h,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:57:39 $"; */
+#ifndef EGLPNUM_TYPENAME_READ_LP_STATE_H
+#define EGLPNUM_TYPENAME_READ_LP_STATE_H
+
+/****************************************************************************/
+/* */
+/* Routines to support Reading LP Files */
+/* */
+/****************************************************************************/
+
+/*
+ * -) anything after '\' is comment
+ * -) variables consist of a-z A-Z 0-9!"#$%(),;.?@_`'{}|~
+ * don't start with a digit or '.'
+ */
+
+#include "eg_lpnum.h"
+#include "symtab.h"
+
+#include "readline_EGLPNUM_TYPENAME.h"
+
+
+typedef struct EGLPNUM_TYPENAME_ILLread_lp_state
+{
+ EGLPNUM_TYPENAME_qsline_reader *file;
+ const char *file_name;
+ char *p;
+ EGLPNUM_TYPE bound_val;
+ int interactive;
+ int line_num;
+ int column_index;
+ char realline[ILL_namebufsize];
+ char line[ILL_namebufsize];
+ char field[ILL_namebufsize + 1];
+ char fieldOnFirstCol;
+ char eof;
+ char sense_val;
+}
+EGLPNUM_TYPENAME_ILLread_lp_state;
+
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_init (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ EGLPNUM_TYPENAME_qsline_reader * file,
+ const char *fname,
+ int interactve);
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_next_line (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state);
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_next_var (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state);
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_keyword (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ const char **kwd);
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_bad_keyword (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state);
+extern int EGLPNUM_TYPENAME_ILLtest_lp_state_keyword (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ const char *kwd[]);
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_next_field (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state);
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_next_field_on_line (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state);
+extern void EGLPNUM_TYPENAME_ILLread_lp_state_prev_field (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state);
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_sign (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ EGLPNUM_TYPE * sign);
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_possible_coef (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ EGLPNUM_TYPE * coef,
+ const EGLPNUM_TYPE defValue);
+
+ /* returns 1 iff found a number
+ * otherwise 0 */
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_possible_bound_value (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state);
+
+ /* returns 1 iff found a number
+ * otherwise 0 */
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_colon (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state);
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_has_colon (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state);
+extern int EGLPNUM_TYPENAME_ILLread_lp_statxe_has_colon (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state);
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_next_constraint (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state);
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_sense (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state);
+extern int EGLPNUM_TYPENAME_ILLtest_lp_state_sense (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ int all);
+extern void EGLPNUM_TYPENAME_ILLtest_lp_state_bound_sense (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state);
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_value (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ EGLPNUM_TYPE * d);
+extern int EGLPNUM_TYPENAME_ILLtest_lp_state_next_is (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ const char *str);
+extern int EGLPNUM_TYPENAME_ILLread_lp_state_skip_blanks (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ int wrapLines);
+
+extern int EGLPNUM_TYPENAME_ILLcheck_subject_to (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state);
+
+/*---------------------------------------------------------------------------*/
+/* errors and warnings
+ */
+extern int EGLPNUM_TYPENAME_ILLlp_error (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ const char *format,
+ ...);
+extern void EGLPNUM_TYPENAME_ILLlp_warn (
+ EGLPNUM_TYPENAME_ILLread_lp_state * state,
+ const char *format,
+ ...);
+
+/*---------------------------------------------------------------------------*/
+/* shared with read_mps_state.c
+ */
+extern int EGLPNUM_TYPENAME_ILLget_value (
+ char *line,
+ EGLPNUM_TYPE * coef);
+
+#endif
diff --git a/qsopt_ex/read_mps.c b/qsopt_ex/read_mps.c
new file mode 100644
index 0000000..92e0158
--- /dev/null
+++ b/qsopt_ex/read_mps.c
@@ -0,0 +1,522 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: read_mps_state.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+
+/****************************************************************************/
+/* */
+/* Routines to Support Reading MPS Files */
+/* */
+/****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdarg.h>
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "eg_lpnum.h"
+#include "eg_io.h"
+#include "except.h"
+
+#include "mps_EGLPNUM_TYPENAME.h"
+#include "rawlp_EGLPNUM_TYPENAME.h"
+#include "read_mps_EGLPNUM_TYPENAME.h"
+#include "read_lp_EGLPNUM_TYPENAME.h" /* for EGLPNUM_TYPENAME_ILLget_value */
+#include "format_EGLPNUM_TYPENAME.h"
+
+
+static int TRACE = 0;
+
+#define END_LINE(p) (((*(p)) == '$' || (*(p)) == '\n' || (*(p)) == '\0') ? 1 : 0)
+
+static int mps_skip_comment (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state);
+static char ILLmps_next_field_is_number (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state);
+
+int EGLPNUM_TYPENAME_ILLmps_state_init (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPENAME_qsline_reader * file,
+ const char *fname)
+{
+ int i, rval = 0;
+
+ ILL_FAILtrue (file == 0, "need file");
+ state->p = 0;
+ state->file_name = fname;
+ state->file = file;
+
+ for (i = 0; i < ILL_MPS_N_SECTIONS; i++)
+ {
+ state->section[i] = 0;
+ }
+ state->active = ILL_MPS_NONE;
+ state->intvar = 0;
+ state->sosvar = 0;
+ state->line_num = 0;
+ state->p = 0;
+
+ state->obj = 0;
+ state->line[0] = '\0';
+ state->key[0] = '\0';
+ state->field[0] = '\0';
+
+CLEANUP:
+ ILL_RESULT (rval, "EGLPNUM_TYPENAME_ILLmps_state_init");
+}
+
+int EGLPNUM_TYPENAME_ILLmps_next_line (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state)
+{
+ int rval = 0;
+
+ /* if field 3 or 5 start with $ rest of line is interpreted as comment */
+ state->line[0] = '\0';
+ state->p = 0;
+ while (EGLPNUM_TYPENAME_ILLline_reader_get (state->line, ILL_namebufsize - 2, state->file)
+ != 0)
+ {
+ state->line_num++;
+ state->key[0] = '\0';
+ state->field[0] = '\0';
+ state->field_num = 1;
+ state->p = state->line;
+ if (!EGLPNUM_TYPENAME_ILL_ISBLANK ((state->line)))
+ {
+ if (state->line[0] == '*' || state->line[0] == '\n')
+ {
+ continue; /* comment or blank line */
+ }
+ else
+ {
+ if (sscanf (state->p, "%s", state->key) == 1)
+ {
+ state->p += strlen (state->key);
+ while (EGLPNUM_TYPENAME_ILL_ISBLANK (state->p))
+ {
+ state->p++;
+ }
+ if (sscanf (state->p, "%s", state->field) == 1)
+ {
+ state->p += strlen (state->field);
+ }
+ else
+ {
+ ILL_FAILfalse (state->field[0] == '\0', "sscanf problem?");
+ }
+ }
+ else
+ {
+ ILL_FAILfalse (0, "should almost never happen");
+ }
+ }
+ }
+ else
+ {
+ while (EGLPNUM_TYPENAME_ILL_ISBLANK (state->p))
+ {
+ state->p++;
+ }
+ if (sscanf (state->p, "%s", state->field) < 1)
+ {
+ continue; /* nothing more on line */
+ }
+ else
+ {
+ if (state->field[0] == '\0')
+ {
+ continue; /* found empty string */
+ }
+ state->p += strlen (state->field);
+ }
+ }
+ return 0;
+ }
+CLEANUP:
+ return 1; /* end of file */
+}
+
+/* fields 3,5,7,... may start with '$' signifying comment
+ * ==> if we find a '$' as next non blank and
+ * we read 2,4,6,... fields successfully so far
+ * we have a comment
+ */
+static int mps_skip_comment (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state)
+{
+ int rval;
+
+ while (EGLPNUM_TYPENAME_ILL_ISBLANK (state->p))
+ {
+ state->p++;
+ }
+ rval = ((*state->p == '$') && (state->field_num >= 2) &&
+ (state->field_num % 2 == 0));
+ return rval;
+}
+
+int EGLPNUM_TYPENAME_ILLmps_next_field (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state)
+{
+ state->field[0] = '\0';
+ if (!mps_skip_comment (state))
+ {
+ if (sscanf (state->p, "%s", state->field) == 1)
+ {
+ state->p += strlen (state->field) + 1;
+ state->field_num++;
+ return 0;
+ }
+ }
+ return 1; /* no more fields */
+}
+
+static char get_double (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ int peek,
+ EGLPNUM_TYPE * coef)
+{
+ char ok = 0;
+ int len, rval = 0;
+
+ ILL_FAILfalse (state != 0, "must have state");
+ if (mps_skip_comment (state))
+ return 0;
+ len = EGLPNUM_TYPENAME_ILLget_value (state->p, coef);
+ if (len > 0)
+ {
+ if (!peek)
+ {
+ state->p += len;
+ state->field_num++;
+ }
+ ok = 1;
+ }
+CLEANUP:
+ ILL_RESULT (ok, "get_double");
+}
+
+int EGLPNUM_TYPENAME_ILLmps_next_coef (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPE * coef)
+{
+ int len = 0;
+
+ if (!mps_skip_comment (state))
+ {
+ len = get_double (state, 0, coef);
+ }
+ ILL_RESULT (!(len > 0), "EGLPNUM_TYPENAME_ILLmps_next_coef");
+}
+
+int EGLPNUM_TYPENAME_ILLmps_next_bound (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPE * coef)
+{
+ int len = 0, sign = 1;
+ char c, *p;
+
+ if (!mps_skip_comment (state))
+ {
+ c = *state->p;
+ if (c == '-')
+ {
+ sign = -1;
+ len = 1;
+ }
+ else
+ {
+ if (c == '+')
+ {
+ len = 1;
+ }
+ }
+ if (!strncasecmp (state->p + len, "INFINITY", (size_t) 8))
+ {
+ len += 8;
+ }
+ else
+ {
+ if (!strncasecmp (state->p + len, "INF", (size_t) 3))
+ {
+ len += 3;
+ }
+ }
+ if (len > 1)
+ {
+ state->p += len;
+ p = state->p;
+ mps_skip_comment (state);
+ if (!END_LINE (state->p) && p == state->p)
+ {
+ /* found no blanks so this INF/INFINITY is the prefix
+ * of something else */
+ state->p -= len;
+ return 1; /* no coef found */
+ }
+ else
+ {
+ if (sign == 1)
+ EGLPNUM_TYPENAME_EGlpNumCopy (*coef, EGLPNUM_TYPENAME_ILL_MAXDOUBLE);
+ else
+ EGLPNUM_TYPENAME_EGlpNumCopy (*coef, EGLPNUM_TYPENAME_ILL_MINDOUBLE);
+ state->field_num++;
+ ILL_RESULT (0, "EGLPNUM_TYPENAME_ILLmps_next_bound");
+ }
+ }
+ if (get_double (state, 0, coef))
+ {
+ ILL_RESULT (0, "EGLPNUM_TYPENAME_ILLmps_next_bound");
+ }
+ else
+ {
+ ILL_RESULT (1, "EGLPNUM_TYPENAME_ILLmps_next_bound"); /* no coef found */
+ }
+ }
+ ILL_RETURN (1, "EGLPNUM_TYPENAME_ILLmps_next_bound");
+}
+
+static char ILLmps_next_field_is_number (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state)
+{
+ EGLPNUM_TYPE d;
+ int len = 0;
+
+ if (!mps_skip_comment (state))
+ {
+ EGLPNUM_TYPENAME_EGlpNumInitVar (d);
+ len = get_double (state, 1, &d);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (d);
+ }
+ return (len > 0);
+}
+
+void EGLPNUM_TYPENAME_ILLmps_check_end_of_line (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state)
+{
+ if (!mps_skip_comment (state))
+ {
+ if (!END_LINE (state->p))
+ {
+ EGLPNUM_TYPENAME_ILLmps_warn (state, "Extra fields on line.");
+ }
+ }
+}
+
+void EGLPNUM_TYPENAME_ILLmps_set_end_of_line (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state)
+{
+ *state->p = '\n';
+}
+
+int EGLPNUM_TYPENAME_ILLmps_set_section (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ const ILLmps_section sec)
+{
+ int rval = 0;
+
+ ILL_FAILfalse (sec != ILL_MPS_NONE, "must be in a proper section");
+ if (state->section[sec])
+ {
+ rval = EGLPNUM_TYPENAME_ILLmps_error (state, "Two %s sections.\n", EGLPNUM_TYPENAME_ILLmps_section_name[sec]);
+ }
+ state->section[sec]++;
+ state->active = sec;
+CLEANUP:
+ ILL_RESULT (rval, "EGLPNUM_TYPENAME_ILLmps_set_section");
+}
+
+int EGLPNUM_TYPENAME_ILLmps_int_sos_mode (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state)
+{
+ if (!strcmp (state->field, "'INTORG'"))
+ {
+ if (state->intvar)
+ {
+ return !EGLPNUM_TYPENAME_ILLmps_error (state, "'INTEND' expected.\n");
+ }
+ else
+ {
+ state->intvar = 1;
+ ILL_RESULT (0, "EGLPNUM_TYPENAME_ILLmps_int_sos_mode");
+ }
+ }
+ if (!strcmp (state->field, "'INTEND'"))
+ {
+ if (state->intvar)
+ {
+ state->intvar = 0;
+ ILL_RESULT (0, "EGLPNUM_TYPENAME_ILLmps_int_sos_mode");
+ }
+ else
+ {
+ return !EGLPNUM_TYPENAME_ILLmps_error (state, "'INTORG' expected.\n");
+ }
+ }
+ if (!strcmp (state->field, "'SOSORG'"))
+ {
+ if (state->sosvar)
+ {
+ return !EGLPNUM_TYPENAME_ILLmps_error (state, "'SOSEND' expected.\n");
+ }
+ else
+ {
+ state->sosvar = 1;
+ ILL_RESULT (0, "EGLPNUM_TYPENAME_ILLmps_int_sos_mode");
+ }
+ }
+ if (!strcmp (state->field, "'SOSEND'"))
+ {
+ if (state->sosvar)
+ {
+ state->sosvar = 0;
+ ILL_RESULT (0, "EGLPNUM_TYPENAME_ILLmps_int_sos_mode");
+ }
+ else
+ {
+ return !EGLPNUM_TYPENAME_ILLmps_error (state, "'SOSORG' expected.\n");
+ }
+ }
+ return EGLPNUM_TYPENAME_ILLmps_error (state, "%s is not a MARKER field.\n", state->field);
+}
+
+const char *EGLPNUM_TYPENAME_ILLmps_possibly_blank_name (
+ const char *field,
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ ILLsymboltab * tab)
+{
+ int ind;
+
+ if (ILLsymboltab_lookup (tab, field, &ind) == 0)
+ {
+ /* Possibly a blank identifier on the line */
+ if (ILLmps_next_field_is_number (state))
+ {
+ /* assume a blank bound ident */
+ return " ";
+ }
+ else
+ {
+ return field;
+ }
+ }
+ else
+ {
+ return field;
+ }
+}
+
+int EGLPNUM_TYPENAME_ILLmps_empty_key (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state)
+{
+ return state->key[0] == '\0';
+}
+
+int EGLPNUM_TYPENAME_ILLmps_empty_field (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state)
+{
+ return state->field[0] == '\0';
+}
+
+static void mps_err (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ int isError,
+ const char *format,
+ va_list args)
+{
+ int rval = 0;
+ const char *type = (isError) ? "MPS Error" : "MPS Warning";
+ int errtype, slen, at;
+ EGLPNUM_TYPENAME_qsformat_error error;
+ char error_desc[256];
+
+ ILL_FAILfalse_no_rval (format != 0, "format != 0");
+ ILL_FAILfalse_no_rval (format[0] != '\0', "format[0] != '0'");
+ ILL_FAILfalse_no_rval (state != 0, "state != 0");
+ ILL_FAILfalse_no_rval (state->file != 0, "state->file != 0");
+
+ if (state->p == 0)
+ {
+ at = -1;
+ }
+ else
+ {
+ ILL_FAILfalse (state->p >= state->line, "state->p >= state->line");
+ at = state->p - state->line;
+ }
+ vsprintf (error_desc, format, args);
+ slen = strlen (error_desc);
+ if ((slen > 0) && error_desc[slen - 1] != '\n')
+ {
+ error_desc[slen] = '\n';
+ error_desc[slen + 1] = '\0';
+ }
+
+ if (state->file->error_collector != 0)
+ {
+ errtype = (isError) ? QS_MPS_FORMAT_ERROR : QS_MPS_FORMAT_WARN;
+ EGLPNUM_TYPENAME_ILLformat_error_create (&error, errtype, error_desc,
+ (int) (state->line_num), state->line, at);
+ EGLPNUM_TYPENAME_ILLformat_error (state->file->error_collector, &error);
+ EGLPNUM_TYPENAME_ILLformat_error_delete (&error);
+ }
+ else
+ {
+ QSlog("%s %d: %s\t", state->file_name, state->line_num,
+ state->line);
+ QSlog("%s: %s", type, error_desc);
+ }
+CLEANUP:
+ ;
+}
+
+int EGLPNUM_TYPENAME_ILLmps_error (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ const char *format,
+ ...)
+{
+ va_list args;
+
+ va_start (args, format);
+ mps_err (state, TRUE, format, args);
+ /* ILL_RESULT(1, "EGLPNUM_TYPENAME_ILLmps_error"); */
+ return 1;
+}
+
+void EGLPNUM_TYPENAME_ILLmps_warn (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ const char *format,
+ ...)
+{
+ va_list args;
+
+ va_start (args, format);
+ if (format != 0)
+ {
+ mps_err (state, FALSE, format, args);
+ }
+}
diff --git a/qsopt_ex/read_mps.h b/qsopt_ex/read_mps.h
new file mode 100644
index 0000000..b0e1196
--- /dev/null
+++ b/qsopt_ex/read_mps.h
@@ -0,0 +1,97 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* $RCSfile: rd_mps.h,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:57:39 $ */
+#ifndef EGLPNUM_TYPENAME_READ_MPS_STATE_H
+#define EGLPNUM_TYPENAME_READ_MPS_STATE_H
+
+#include "symtab.h"
+#include "basicdefs.h"
+
+#include "readline_EGLPNUM_TYPENAME.h"
+
+
+typedef struct EGLPNUM_TYPENAME_ILLread_mps_state_struct
+{
+ int section[ILL_MPS_N_SECTIONS];
+ ILLmps_section active;
+ const char *file_name;
+ EGLPNUM_TYPENAME_qsline_reader *file;
+ unsigned int line_num;
+ unsigned int field_num; /* number of successfully read fields on line */
+ int intvar;
+ int sosvar;
+ char line[ILL_namebufsize];
+ char key[ILL_namebufsize];
+ char field[ILL_namebufsize];
+ char *obj;
+ char *p; /* ptr to next 'unread' character */
+}
+EGLPNUM_TYPENAME_ILLread_mps_state;
+
+extern int EGLPNUM_TYPENAME_ILLmps_state_init (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPENAME_qsline_reader * file,
+ const char *fname);
+extern void EGLPNUM_TYPENAME_ILLmps_state_clear (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state);
+extern int EGLPNUM_TYPENAME_ILLmps_set_section (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ const ILLmps_section sec);
+
+extern int EGLPNUM_TYPENAME_ILLmps_next_line (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state);
+extern int EGLPNUM_TYPENAME_ILLmps_next_field (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state);
+extern int EGLPNUM_TYPENAME_ILLmps_next_coef (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPE * coef);
+extern int EGLPNUM_TYPENAME_ILLmps_next_bound (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ EGLPNUM_TYPE * coef);
+extern void EGLPNUM_TYPENAME_ILLmps_check_end_of_line (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state);
+extern void EGLPNUM_TYPENAME_ILLmps_set_end_of_line (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state);
+
+extern int EGLPNUM_TYPENAME_ILLmps_int_sos_mode (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state);
+
+extern const char *EGLPNUM_TYPENAME_ILLmps_possibly_blank_name (
+ const char *field,
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ ILLsymboltab * tab);
+extern int EGLPNUM_TYPENAME_ILLmps_empty_key (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state);
+extern int EGLPNUM_TYPENAME_ILLmps_empty_field (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state);
+
+extern int EGLPNUM_TYPENAME_ILLmps_error (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ const char *format,
+ ...);
+extern void EGLPNUM_TYPENAME_ILLmps_warn (
+ EGLPNUM_TYPENAME_ILLread_mps_state * state,
+ const char *format,
+ ...);
+
+#endif
diff --git a/qsopt_ex/reader.c b/qsopt_ex/reader.c
new file mode 100644
index 0000000..32db02e
--- /dev/null
+++ b/qsopt_ex/reader.c
@@ -0,0 +1,283 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: reader.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+
+#include "reader.h"
+#include "qstruct.h"
+#include "qsopt.h"
+
+static int TRACE = 0;
+static int TEST_ERROR_COLLECTOR = 0;
+static int TEST_ERROR_MEMORY = 0;
+
+static char *fname = (char *) NULL;
+static char *out_lp = (char *) NULL;
+static char *out_mps = (char *) NULL;
+static int lpfile = 0;
+static int stats = 0;
+
+static void usage (
+ char *s);
+
+static int parseargs (
+ int ac,
+ char **av);
+
+static int add_error (
+ void *dest,
+ QSformat_error error)
+{
+ const char *type = "Error";
+ const char *line;
+ int tp, i, at;
+ FILE *out = (FILE *) dest;
+
+ at = QSerror_get_pos (error);
+ tp = QSerror_get_type (error);
+ type = QSformat_error_type_string (tp);
+
+ fprintf (out, "ADD: ");
+ fprintf (out, "%s line %d pos %d\n",
+ type, QSerror_get_line_number (error), at);
+ line = QSerror_get_line (error);
+ if (line != NULL)
+ {
+ fprintf (out, "LINE %s", line);
+ if (at >= 0)
+ {
+ fprintf (out, ".....");
+ for (i = 0; i <= (at - 1); i++)
+ {
+ if (line[i] == '\t')
+ {
+ fputc ('\t', out);
+ }
+ else
+ {
+ fputc ('.', out);
+ }
+ }
+ fprintf (out, "^\n");
+ }
+ }
+ else
+ {
+ fprintf (out, "NO LINE\n");
+ }
+
+ fprintf (out, "MSG: %s\n", QSerror_get_desc (error));
+ return 0;
+}
+
+QSLIB_INTERFACE int reader_main (
+ int ac,
+ char **av)
+{
+ int rval = 0;
+ int rvalmps = 0;
+ int rvallp = 0;
+ QSdata *p = NULL;
+ ILLutil_timer timer_read;
+ ILLutil_timer timer_write;
+ FILE *fin = NULL;
+ QSline_reader reader = NULL;
+ QSerror_collector collector = NULL;
+ QSerror_memory error_mem = NULL;
+ QSformat_error e = NULL;
+
+ if (parseargs (ac, av))
+ goto CLEANUP;
+
+ ILLutil_init_timer (&timer_read, "READER_READ");
+ ILLutil_start_timer (&timer_read);
+ if (TEST_ERROR_COLLECTOR || TEST_ERROR_MEMORY)
+ {
+ fin = fopen (fname, "r");
+ reader = QSline_reader_new ((void *) fgets, fin);
+ if (TEST_ERROR_COLLECTOR)
+ {
+ collector = QSerror_collector_new ((void *) add_error, stderr);
+ }
+ if (TEST_ERROR_MEMORY)
+ {
+ error_mem = QSerror_memory_create (0);
+ ILL_CHECKnull (error_mem, "Could not make error memory");
+ collector = QSerror_memory_collector_new (error_mem);
+ }
+ if (fin == NULL)
+ {
+ fprintf (stderr, "Can't open \"%s\" for reading.\n", fname);
+ }
+ rval = (fin == NULL) || (reader == NULL) || (collector == NULL);
+ ILL_CLEANUP_IF (rval);
+
+ QSline_reader_set_error_collector (reader, collector);
+ p = QSget_prob (reader, fname, (lpfile == 0) ? "MPS" : "LP");
+
+ if (TEST_ERROR_MEMORY)
+ {
+ int n = QSerror_memory_get_nerrors (error_mem);
+
+ fprintf (stderr, "#error %d\n", n);
+ for (e = QSerror_memory_get_last_error (error_mem);
+ e != NULL; e = QSerror_memory_get_prev_error (e))
+ {
+ QSerror_print (stderr, e);
+ }
+ }
+ }
+ else
+ {
+ if (lpfile == 0)
+ {
+ p = QSread_prob (fname, "MPS");
+ }
+ else
+ {
+ p = QSread_prob (fname, "LP");
+ }
+ }
+ ILL_IFTRACE ("QSread_prob %s\n", fname);
+ ILLutil_stop_timer (&timer_read, 1);
+ rval = (p == NULL);
+ fprintf (stdout,
+ "read \"%s\" %s.\n", fname, (rval == 0) ? "succeeded" : "failed");
+ ILL_CLEANUP_IF (rval);
+
+ if (stats)
+ {
+ fprintf (stdout, "\n");
+ fprintf (stdout, "The problem \"%s\" has %d rows and %d cols.\n",
+ QSget_probname (p), QSget_rowcount (p), QSget_colcount (p));
+ }
+ ILLutil_init_timer (&timer_write, "READER_WRITE");
+ ILLutil_start_timer (&timer_write);
+ if (out_mps)
+ {
+ fprintf (stdout, "\n");
+ rvalmps = QSwrite_prob (p, out_mps, "MPS");
+ fprintf (stdout, "write \"%s\" %s.\n", out_mps,
+ (rvalmps == 0) ? "succeeded" : "failed");
+ }
+ if (out_lp)
+ {
+ fprintf (stdout, "\n");
+ rvallp = QSwrite_prob (p, out_lp, "LP");
+ fprintf (stdout, "write \"%s\" %s.\n", out_lp,
+ (rvallp == 0) ? "succeeded" : "failed");
+ }
+ ILLutil_stop_timer (&timer_write, 1);
+
+ rval = rvalmps || rvallp;
+ ILL_CLEANUP_IF (rval);
+
+CLEANUP:
+
+ if (p != NULL)
+ QSfree_prob (p);
+ if (fin != NULL)
+ fclose (fin);
+ if (reader != NULL)
+ QSline_reader_free (reader);
+ if (collector != NULL)
+ QSerror_collector_free (collector);
+ if (error_mem != NULL)
+ QSerror_memory_free (error_mem);
+
+ return rval; /* main return */
+}
+
+static void usage (
+ char *s)
+{
+ fprintf (stderr, "Usage: %s [- below -] prob_file\n", s);
+ fprintf (stderr, " -L input file is in lp format (default: mps)\n");
+ fprintf (stderr, " -s print information about problem to stdout\n");
+ fprintf (stderr, " -l f write lp in LP format to file f\n");
+ fprintf (stderr, " -m f write lp in MPS format to file f\n");
+#if 0
+ fprintf (stderr, " -E test error_memory\n");
+ fprintf (stderr, " -e test error_collector\n");
+#endif
+}
+
+static int parseargs (
+ int ac,
+ char **av)
+{
+ int c;
+ int boptind = 1;
+ char *boptarg = (char *) NULL;
+
+ while ((c =
+ ILLutil_bix_getopt (ac, av, "Ll:m:tseE", &boptind, &boptarg)) != EOF)
+ switch (c)
+ {
+ case 'L':
+ lpfile = 1;
+ break;
+ case 'l':
+ out_lp = boptarg;
+ break;
+ case 'm':
+ out_mps = boptarg;
+ break;
+ case 's':
+ stats = 1;
+ break;
+ case 't':
+ TRACE++;
+ break;
+#if 0
+ case 'E':
+ TEST_ERROR_MEMORY++;
+ break;
+ case 'e':
+ TEST_ERROR_COLLECTOR++;
+ break;
+#endif
+ case '?':
+ default:
+ usage (av[0]);
+ return 1;
+ }
+
+ if (boptind != (ac - 1))
+ {
+ usage (av[0]);
+ return 1;
+ }
+
+ fname = av[boptind++];
+ return 0;
+}
+
+
+#ifndef WIN32
+int main (
+ int ac,
+ char **av)
+{
+ return reader_main (ac, av);
+}
+#endif
diff --git a/qsopt_ex/reader.h b/qsopt_ex/reader.h
new file mode 100644
index 0000000..03bcd82
--- /dev/null
+++ b/qsopt_ex/reader.h
@@ -0,0 +1,33 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: reader.h,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:57:39 $"; */
+#ifndef READER_H
+#define READER_H
+
+#include "qsopt.h"
+
+QSLIB_INTERFACE int reader_main (
+ int argc,
+ char **argv);
+
+#endif
diff --git a/qsopt_ex/readline.c b/qsopt_ex/readline.c
new file mode 100644
index 0000000..d8f35e2
--- /dev/null
+++ b/qsopt_ex/readline.c
@@ -0,0 +1,62 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCS_INFO = "$Id: line_reader.c,v 1.2 2003/11/05 16:49:52 meven Exp $"; */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "allocrus.h"
+#include "eg_io.h"
+#include "except.h"
+#include "readline_EGLPNUM_TYPENAME.h"
+
+
+/* #ifdef _WINDOWS*/
+EGLPNUM_TYPENAME_qsline_reader *EGLPNUM_TYPENAME_ILLline_reader_new (
+ EGLPNUM_TYPENAME_qsread_line_fct fct,
+ void *data_src)
+{
+ EGLPNUM_TYPENAME_qsline_reader *reader;
+ int rval = 0;
+
+ ILL_NEW (reader, EGLPNUM_TYPENAME_qsline_reader);
+ if (reader != NULL)
+ {
+ reader->read_line_fct = fct;
+ reader->data_src = data_src;
+ reader->error_collector = NULL;
+ }
+CLEANUP:
+ return reader;
+}
+
+void EGLPNUM_TYPENAME_ILLline_reader_free (
+ EGLPNUM_TYPENAME_qsline_reader * reader)
+{
+ ILL_IFFREE (reader, EGLPNUM_TYPENAME_qsline_reader);
+}
+
+/* #endif */
diff --git a/qsopt_ex/readline.h b/qsopt_ex/readline.h
new file mode 100644
index 0000000..ac2f14c
--- /dev/null
+++ b/qsopt_ex/readline.h
@@ -0,0 +1,64 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCSINFO $Id: rdline.h,v 1.2 2003/11/05 16:57:39 meven Exp $ */
+#ifndef EGLPNUM_TYPENAME_LINE_READER_FILE_H
+#define EGLPNUM_TYPENAME_LINE_READER_FILE_H
+
+#include "qsopt_EGLPNUM_TYPENAME.h"
+#include "format_EGLPNUM_TYPENAME.h"
+
+/* #ifdef _WINDOWS */
+typedef char *(
+ *EGLPNUM_TYPENAME_qsread_line_fct) (
+ char *s,
+ int size,
+ void *src);
+
+typedef struct EGLPNUM_TYPENAME_qsline_reader
+{
+ EGLPNUM_TYPENAME_qsread_line_fct read_line_fct;
+ void *data_src;
+ struct EGLPNUM_TYPENAME_qserror_collector *error_collector;
+}
+EGLPNUM_TYPENAME_qsline_reader;
+
+EGLPNUM_TYPENAME_qsline_reader *EGLPNUM_TYPENAME_ILLline_reader_new (
+ EGLPNUM_TYPENAME_qsread_line_fct fct,
+ void *data_src);
+void EGLPNUM_TYPENAME_ILLline_reader_free (
+ EGLPNUM_TYPENAME_qsline_reader * reader);
+
+#define EGLPNUM_TYPENAME_ILLline_reader_get(s, size, reader) \
+ (reader)->read_line_fct(s, size, (reader)->data_src)
+ /* used by parsers to retrieve next input line */
+/* #else
+ *
+ * typedef FILE EGLPNUM_TYPENAME_qsline_reader;
+ *
+ * #define EGLPNUM_TYPENAME_ILLline_reader_new(fct, data) ((FILE*) (data))
+ * #define EGLPNUM_TYPENAME_ILLline_reader_free(reader)
+ * #define EGLPNUM_TYPENAME_ILLline_reader_get(s, size, reader) fgets(s,size,reader)
+ * #endif
+ */
+
+#endif
diff --git a/qsopt_ex/reporter.c b/qsopt_ex/reporter.c
new file mode 100644
index 0000000..52e2f62
--- /dev/null
+++ b/qsopt_ex/reporter.c
@@ -0,0 +1,94 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCS_INFO = "$Id: reporter.c,v 1.1 2003/11/05 16:49:52 meven Exp $"; */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "reporter.h"
+#include "except.h"
+
+
+int ILL_fprintf (
+ void *dest,
+ const char *s)
+{
+ if (s != NULL)
+ return fputs(s, (FILE *)dest);
+ return 0;
+}
+
+void ILLstring_reporter_init (
+ qsstring_reporter * reporter,
+ qsreport_string_fct fct,
+ void *dest)
+{
+ int rval = 0;
+
+ ILL_FAILfalse (reporter != NULL, "Must get non NULL reporter");
+ if (reporter != NULL)
+ {
+ reporter->report_fct = fct;
+ reporter->dest = dest;
+ }
+CLEANUP:
+ return;
+}
+
+void ILLstring_reporter_copy (
+ qsstring_reporter * dest,
+ qsstring_reporter * src)
+{
+ *dest = *src;
+}
+
+
+#ifdef REPORTER_MAIN
+static int string_reporter_main (
+ int ac,
+ char **av)
+{
+ int i = 0;
+ qsstring_reporter reporter;
+
+ ILLstring_reporter_init (&reporter, ILL_fprintf, stdout);
+ for (i = 0; i < ac; i++)
+ {
+ (void) ILLstring_report (av[i], &reporter);
+ (void) ILLstring_report ("\n", &reporter);
+ }
+ (void) ILLstring_report (NULL, &reporter);
+
+ return 0;
+}
+
+int main (
+ int ac,
+ char **av)
+{
+ return string_reporter_main (ac, av);
+}
+#endif
diff --git a/qsopt_ex/reporter.h b/qsopt_ex/reporter.h
new file mode 100644
index 0000000..76be2e0
--- /dev/null
+++ b/qsopt_ex/reporter.h
@@ -0,0 +1,59 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* $RCSfile: reporter.h,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:57:39 $ */
+#ifndef REPORTER_FILE
+#define REPORTER_FILE
+
+#include "eg_io.h"
+
+typedef int (
+ *qsreport_string_fct) (
+ void *dest,
+ const char *s);
+
+typedef struct qsstring_reporter
+{
+ qsreport_string_fct report_fct;
+ void *dest;
+}
+qsstring_reporter;
+
+extern int ILL_fprintf (
+ void *dest,
+ const char *s);
+
+void ILLstring_reporter_init (
+ qsstring_reporter * reporter,
+ qsreport_string_fct fct,
+ void *dest);
+
+void ILLstring_reporter_copy (
+ qsstring_reporter * dest,
+ qsstring_reporter * src);
+
+#define ILLstring_report(s, reporter) \
+ ((reporter)->report_fct((reporter)->dest, s) < 0)
+ /* used from with ILL fct to report progress */
+
+/* REPORTER_FILE */
+#endif
diff --git a/qsopt_ex/simplex.c b/qsopt_ex/simplex.c
new file mode 100644
index 0000000..adfbdaf
--- /dev/null
+++ b/qsopt_ex/simplex.c
@@ -0,0 +1,3026 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: simplex.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+static int TRACE = 0;
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "logging-private.h"
+
+#include "eg_lpnum.h"
+#include "eg_io.h"
+#include "except.h"
+#include "zeit.h"
+#include "util.h"
+
+#define QSOPT_CURRENT_PRECICION
+#include "basicdefs.h"
+#include "lpdata_EGLPNUM_TYPENAME.h"
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+
+#include "stddefs.h"
+#include "fct_EGLPNUM_TYPENAME.h"
+#include "ratio_EGLPNUM_TYPENAME.h"
+#include "price_EGLPNUM_TYPENAME.h"
+#include "basis_EGLPNUM_TYPENAME.h"
+#include "simplex_EGLPNUM_TYPENAME.h"
+#include "dstruct_EGLPNUM_TYPENAME.h"
+#include "qstruct_EGLPNUM_TYPENAME.h"
+#include "qsopt_EGLPNUM_TYPENAME.h"
+#include "lib_EGLPNUM_TYPENAME.h" /* for EGLPNUM_TYPENAME_ILLlib_writebasis */
+#include "lp_EGLPNUM_TYPENAME.h" /* for EGLPNUM_TYPENAME_ILLwrite_lp */
+
+
+static void init_lp_status_info (
+ EGLPNUM_TYPENAME_lp_status_info * ls),
+ init_simplex_tols (
+ EGLPNUM_TYPENAME_lpinfo * lp),
+ monitor_iter (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * p,
+ EGLPNUM_TYPENAME_iter_info * it,
+ int cphase),
+ get_current_stat (
+ EGLPNUM_TYPENAME_lp_status_info * p,
+ int algorithm,
+ int *bstat);
+
+static int terminate_simplex (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int phase,
+ EGLPNUM_TYPENAME_iter_info * it),
+ primal_phaseI_step (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * pinf,
+ EGLPNUM_TYPENAME_svector * updz,
+ EGLPNUM_TYPENAME_svector * wz,
+ EGLPNUM_TYPENAME_iter_info * it),
+ primal_phaseII_step (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * pinf,
+ EGLPNUM_TYPENAME_svector * updz,
+ EGLPNUM_TYPENAME_svector * wz,
+ EGLPNUM_TYPENAME_iter_info * it),
+ dual_phaseI_step (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * pinf,
+ EGLPNUM_TYPENAME_svector * updz,
+ EGLPNUM_TYPENAME_svector * wz,
+ EGLPNUM_TYPENAME_iter_info * it),
+ dual_phaseII_step (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * pinf,
+ EGLPNUM_TYPENAME_svector * updz,
+ EGLPNUM_TYPENAME_svector * wz,
+ EGLPNUM_TYPENAME_iter_info * it),
+ report_value (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_iter_info * it,
+ const char *value_name,
+ EGLPNUM_TYPE value);
+
+
+void EGLPNUM_TYPENAME_ILLsimplex_init_lpinfo (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ EGLPNUM_TYPENAME_ILLbasis_init_basisinfo (lp);
+ EGLPNUM_TYPENAME_init_internal_lpinfo (lp);
+}
+
+void EGLPNUM_TYPENAME_ILLsimplex_free_lpinfo (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ if (lp)
+ {
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->lz);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->uz);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->cz);
+ EGLPNUM_TYPENAME_ILLbasis_free_basisinfo (lp);
+ EGLPNUM_TYPENAME_free_internal_lpinfo (lp);
+ }
+}
+
+void EGLPNUM_TYPENAME_ILLsimplex_load_lpinfo (
+ EGLPNUM_TYPENAME_ILLlpdata * qslp,
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ lp->basisid = -1;
+ lp->maxiter = 500000;
+ lp->maxtime = 300000;
+ //lp->iterskip = 10;
+ lp->iterskip = 100;
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->objbound, EGLPNUM_TYPENAME_INFTY);
+ lp->O = qslp;
+}
+
+void EGLPNUM_TYPENAME_ILLsimplex_set_bound (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ const EGLPNUM_TYPE * objbound,
+ int sense)
+{
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->objbound, *objbound);
+ if (sense == EGLPNUM_TYPENAME_ILL_MAX)
+ EGLPNUM_TYPENAME_EGlpNumSign (lp->objbound);
+}
+
+static void init_lp_status_info (
+ EGLPNUM_TYPENAME_lp_status_info * ls)
+{
+ ls->optimal = 0;
+ ls->primal_feasible = 0;
+ ls->primal_infeasible = 0;
+ ls->primal_unbounded = 0;
+ ls->dual_feasible = 0;
+ ls->dual_infeasible = 0;
+ ls->dual_unbounded = 0;
+}
+
+static void init_simplex_tols (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->tol->pfeas_tol, EGLPNUM_TYPENAME_PFEAS_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->tol->dfeas_tol, EGLPNUM_TYPENAME_DFEAS_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->tol->pivot_tol, EGLPNUM_TYPENAME_PIVOT_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->tol->szero_tol, EGLPNUM_TYPENAME_SZERO_TOLER);
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->tol->ip_tol, lp->tol->pfeas_tol);
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->tol->id_tol, lp->tol->dfeas_tol);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (lp->tol->ip_tol))
+ {
+#if VERBOSE_LEVEL <= DEBUG
+ MESSAGE (VERBOSE_LEVEL, "ip_tol %lg", EGLPNUM_TYPENAME_EGlpNumToLf (lp->tol->ip_tol));
+ MESSAGE (VERBOSE_LEVEL, "eps %lg", EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_epsLpNum));
+ MESSAGE (VERBOSE_LEVEL, "EGLPNUM_TYPENAME_PFEAS_TOLER %lg", EGLPNUM_TYPENAME_EGlpNumToLf (EGLPNUM_TYPENAME_PFEAS_TOLER));
+#endif
+ EGLPNUM_TYPENAME_EGlpNumDivUiTo (lp->tol->ip_tol, 2UL);
+ }
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqqZero (lp->tol->id_tol))
+ {
+#if VERBOSE_LEVEL <= DEBUG
+ MESSAGE (VERBOSE_LEVEL, "id_tol %lg", EGLPNUM_TYPENAME_EGlpNumToLf (lp->tol->id_tol));
+#endif
+ EGLPNUM_TYPENAME_EGlpNumDivUiTo (lp->tol->id_tol, 2UL);
+ }
+}
+
+void EGLPNUM_TYPENAME_init_internal_lpinfo (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ int rval = 0;
+
+ lp->nrows = 0;
+ lp->nnbasic = 0;
+ lp->localrows = 0;
+ lp->rowcnt = 0;
+ lp->rowbeg = 0;
+ lp->rowind = 0;
+ lp->rowval = 0;
+ lp->cz = 0;
+ lp->lz = 0;
+ lp->uz = 0;
+ lp->xbz = 0;
+ lp->piz = 0;
+ lp->dz = 0;
+ lp->pIxbz = 0;
+ lp->pIpiz = 0;
+ lp->pIdz = 0;
+ lp->vtype = 0;
+ lp->vclass = 0;
+ lp->iwork = 0;
+ lp->upd.perm = 0;
+ lp->upd.ix = 0;
+ lp->upd.t = 0;
+ lp->bfeas = 0;
+ lp->dfeas = 0;
+ lp->tol = 0;
+ lp->cnts = 0;
+ lp->bchanges = 0;
+ lp->cchanges = 0;
+ EGLPNUM_TYPENAME_ILLsvector_init (&(lp->zz));
+ EGLPNUM_TYPENAME_ILLsvector_init (&(lp->yjz));
+ EGLPNUM_TYPENAME_ILLsvector_init (&(lp->zA));
+ EGLPNUM_TYPENAME_ILLsvector_init (&(lp->work));
+ EGLPNUM_TYPENAME_ILLsvector_init (&(lp->srhs));
+ EGLPNUM_TYPENAME_ILLsvector_init (&(lp->ssoln));
+ ILL_SAFE_MALLOC (lp->tol, 1, EGLPNUM_TYPENAME_tol_struct);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (lp->tol->pfeas_tol);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (lp->tol->dfeas_tol);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (lp->tol->pivot_tol);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (lp->tol->szero_tol);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (lp->tol->ip_tol);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (lp->tol->id_tol);
+ ILL_SAFE_MALLOC (lp->cnts, 1, EGLPNUM_TYPENAME_count_struct);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (lp->cnts->y_ravg);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (lp->cnts->z_ravg);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (lp->cnts->za_ravg);
+CLEANUP:
+ if (rval)
+ {
+ QSlog("no memory, in %s, exit", __func__);
+ exit (1);
+ }
+}
+
+void EGLPNUM_TYPENAME_free_internal_lpinfo (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ EGLPNUM_TYPENAME_bndinfo *binfo = 0;
+ EGLPNUM_TYPENAME_coefinfo *cinfo = 0;
+
+ if (lp->localrows)
+ {
+ ILL_IFFREE (lp->rowcnt, int);
+ ILL_IFFREE (lp->rowbeg, int);
+ ILL_IFFREE (lp->rowind, int);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->rowval);
+ lp->localrows = 0;
+ }
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->lz);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->uz);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->cz);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->xbz);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->piz);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->pIpiz);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->dz);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->pIdz);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->pIxbz);
+
+ ILL_IFFREE (lp->vtype, int);
+ ILL_IFFREE (lp->vclass, char);
+
+ EGLPNUM_TYPENAME_ILLsvector_free (&(lp->zz));
+ EGLPNUM_TYPENAME_ILLsvector_free (&(lp->yjz));
+ EGLPNUM_TYPENAME_ILLsvector_free (&(lp->zA));
+ EGLPNUM_TYPENAME_ILLsvector_free (&(lp->work));
+ EGLPNUM_TYPENAME_ILLsvector_free (&(lp->srhs));
+ EGLPNUM_TYPENAME_ILLsvector_free (&(lp->ssoln));
+ ILL_IFFREE (lp->iwork, int);
+ ILL_IFFREE (lp->upd.perm, int);
+ ILL_IFFREE (lp->upd.ix, int);
+
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->upd.t);
+
+ ILL_IFFREE (lp->bfeas, int);
+ ILL_IFFREE (lp->dfeas, int);
+
+ if (lp->tol)
+ {
+ EGLPNUM_TYPENAME_EGlpNumClearVar (lp->tol->pfeas_tol);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (lp->tol->dfeas_tol);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (lp->tol->pivot_tol);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (lp->tol->szero_tol);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (lp->tol->ip_tol);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (lp->tol->id_tol);
+ ILL_IFFREE (lp->tol, EGLPNUM_TYPENAME_tol_struct);
+ }
+ if (lp->cnts)
+ {
+ EGLPNUM_TYPENAME_EGlpNumClearVar (lp->cnts->y_ravg);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (lp->cnts->z_ravg);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (lp->cnts->za_ravg);
+ ILL_IFFREE (lp->cnts, EGLPNUM_TYPENAME_count_struct);
+ }
+
+ while (lp->bchanges)
+ {
+ binfo = lp->bchanges;
+ EGLPNUM_TYPENAME_EGlpNumClearVar (binfo->pbound);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (binfo->cbound);
+ lp->bchanges = binfo->next;
+ ILL_IFFREE (binfo, EGLPNUM_TYPENAME_bndinfo);
+ }
+
+ while (lp->cchanges)
+ {
+ cinfo = lp->cchanges;
+ EGLPNUM_TYPENAME_EGlpNumClearVar (cinfo->pcoef);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (cinfo->ccoef);
+ lp->cchanges = cinfo->next;
+ ILL_IFFREE (cinfo, EGLPNUM_TYPENAME_coefinfo);
+ }
+}
+
+int EGLPNUM_TYPENAME_build_internal_lpinfo (
+ EGLPNUM_TYPENAME_lpinfo * lp)
+{
+ int rval = 0;
+ int i, n;
+ EGLPNUM_TYPENAME_ILLlpdata *qslp = lp->O;
+ EGLPNUM_TYPENAME_ILLlp_sinfo *S = lp->O->sinfo;
+ EGLPNUM_TYPE *lower, *upper, *obj;
+ EGLPNUM_TYPENAME_ILLlp_rows lprows;
+ EGLPNUM_TYPENAME_ILLmatrix *A;
+
+ init_lp_status_info (&(lp->probstat));
+ init_lp_status_info (&(lp->basisstat));
+
+ if (S != 0)
+ {
+ lp->nrows = S->nrows;
+ lp->ncols = S->ncols;
+ lp->bz = S->rhs;
+ lower = S->lower;
+ upper = S->upper;
+ obj = S->obj;
+ A = &(S->A);
+ }
+ else
+ {
+ lp->nrows = qslp->nrows;
+ lp->ncols = qslp->ncols;
+ lp->bz = qslp->rhs;
+ lower = qslp->lower;
+ upper = qslp->upper;
+ obj = qslp->obj;
+ A = &(qslp->A);
+ }
+
+ lp->matbeg = A->matbeg;
+ lp->matcnt = A->matcnt;
+ lp->matind = A->matind;
+ lp->matval = A->matval;
+
+ lp->nnbasic = lp->ncols - lp->nrows;
+
+ lp->lz = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->ncols);
+ lp->cz = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->ncols);
+ lp->uz = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->ncols);
+ if (!lp->lz || !lp->uz || !lp->cz)
+ {
+ QSlog("EGLPNUM_TYPENAME_build_internal_lpinfo");
+ rval = 1;
+ goto CLEANUP;
+ }
+ for (i = 0; i < lp->ncols; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->lz[i], lower[i]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->uz[i], upper[i]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->cz[i], obj[i]);
+ if (qslp->objsense == EGLPNUM_TYPENAME_ILL_MAX)
+ {
+ EGLPNUM_TYPENAME_EGlpNumSign (lp->cz[i]);
+ }
+ }
+
+ if (!lp->O->rA)
+ {
+ rval = EGLPNUM_TYPENAME_ILLlp_rows_init (&lprows, lp->O, 1);
+ CHECKRVALG (rval, CLEANUP);
+ lp->rowbeg = lprows.rowbeg;
+ lp->rowcnt = lprows.rowcnt;
+ lp->rowind = lprows.rowind;
+ lp->rowval = lprows.rowval;
+ lp->localrows = 1;
+ }
+ else
+ {
+ /* row format exists, just use pointers */
+ lp->rowbeg = lp->O->rA->rowbeg;
+ lp->rowcnt = lp->O->rA->rowcnt;
+ lp->rowind = lp->O->rA->rowind;
+ lp->rowval = lp->O->rA->rowval;
+ lp->localrows = 0;
+ }
+
+ lp->xbz = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+ lp->piz = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+ lp->dz = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nnbasic);
+ lp->final_phase = -1;
+ lp->infub_ix = -1;
+
+ ILL_SAFE_MALLOC (lp->vtype, lp->ncols, int);
+ ILL_SAFE_MALLOC (lp->vclass, lp->ncols, char);
+
+ rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&(lp->zz), lp->nrows);
+ CHECKRVALG (rval, CLEANUP);
+ rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&(lp->yjz), lp->nrows);
+ CHECKRVALG (rval, CLEANUP);
+ rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&(lp->zA), lp->nnbasic);
+ CHECKRVALG (rval, CLEANUP);
+ rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&(lp->work), lp->ncols);
+ CHECKRVALG (rval, CLEANUP);
+ rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&(lp->srhs), lp->nrows);
+ CHECKRVALG (rval, CLEANUP);
+ rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&(lp->ssoln), lp->nrows);
+ CHECKRVALG (rval, CLEANUP);
+ ILL_SAFE_MALLOC (lp->iwork, lp->ncols, int);
+
+ for (i = 0; i < lp->ncols; i++)
+ {
+ lp->work.indx[i] = 0;
+ EGLPNUM_TYPENAME_EGlpNumZero (lp->work.coef[i]);
+ lp->iwork[i] = 0;
+ }
+ n = lp->nrows > lp->ncols ? 2 * (lp->nrows) + 1 : 2 * (lp->ncols) + 1;
+ lp->upd.t = EGLPNUM_TYPENAME_EGlpNumAllocArray (n);
+ ILL_SAFE_MALLOC (lp->upd.perm, n, int);
+ ILL_SAFE_MALLOC (lp->upd.ix, n, int);
+
+
+ ILL_SAFE_MALLOC (lp->bfeas, lp->nrows, int);
+ ILL_SAFE_MALLOC (lp->dfeas, lp->nnbasic, int);
+
+ init_simplex_tols (lp);
+ EGLPNUM_TYPENAME_ILLfct_init_counts (lp);
+
+ lp->nbchange = 0;
+ lp->ncchange = 0;
+
+ lp->pIratio = RATIOTEST_HARRIS;
+ lp->pIIratio = RATIOTEST_HARRIS;
+ lp->dIratio = RATIOTEST_HARRIS;
+ lp->dIIratio = RATIOTEST_HARRIS;
+ lp->starttime = ILLutil_zeit ();
+ ILLutil_sprand (1, &(lp->rstate));
+
+CLEANUP:
+ if (rval)
+ EGLPNUM_TYPENAME_free_internal_lpinfo (lp);
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLsimplex_retest_psolution (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * p,
+ int phase,
+ EGLPNUM_TYPENAME_feas_info * fi)
+{
+ int rval = 0;
+ int fbid = lp->fbasisid;
+ int bid = lp->basisid;
+ EGLPNUM_TYPE *ptol = &(lp->tol->pfeas_tol);
+ EGLPNUM_TYPE *dtol = &(lp->tol->dfeas_tol);
+ EGLPNUM_TYPE *iptol = &(lp->tol->ip_tol);
+ EGLPNUM_TYPE *idtol = &(lp->tol->id_tol);
+
+ fi->pstatus = -1;
+ fi->dstatus = -1;
+ if (fbid < bid - PARAM_PRIMAL_REFACTORGAP)
+ {
+ rval = EGLPNUM_TYPENAME_ILLbasis_refactor (lp);
+ CHECKRVALG (rval, CLEANUP);
+ }
+ if (fbid < bid - PARAM_PRIMAL_RESOLVEGAP)
+ EGLPNUM_TYPENAME_ILLfct_compute_xbz (lp);
+
+ if (phase == PRIMAL_PHASEII)
+ {
+ if (fbid < bid - PARAM_PRIMAL_RESOLVEGAP)
+ {
+ EGLPNUM_TYPENAME_ILLfct_compute_piz (lp);
+ EGLPNUM_TYPENAME_ILLfct_compute_dz (lp);
+ if (p != NULL && p->p_strategy == COMPLETE_PRICING)
+ EGLPNUM_TYPENAME_ILLprice_compute_dual_inf (lp, p, NULL, 0, PRIMAL_PHASEII);
+ }
+ EGLPNUM_TYPENAME_ILLfct_compute_pobj (lp);
+ EGLPNUM_TYPENAME_ILLfct_check_pfeasible (lp, fi, *ptol);
+ EGLPNUM_TYPENAME_ILLfct_check_dfeasible (lp, fi, *dtol);
+ }
+ else if (phase == PRIMAL_PHASEI)
+ {
+ EGLPNUM_TYPENAME_ILLfct_check_pfeasible (lp, fi, *iptol);
+ if (fi->pstatus != PRIMAL_FEASIBLE)
+ {
+ if (lp->pIpiz)
+ {
+ EGLPNUM_TYPENAME_ILLfct_compute_phaseI_piz (lp);
+ EGLPNUM_TYPENAME_ILLfct_compute_phaseI_dz (lp);
+ EGLPNUM_TYPENAME_ILLfct_check_pIdfeasible (lp, fi, *idtol);
+ if (p != NULL && p->p_strategy == COMPLETE_PRICING)
+ EGLPNUM_TYPENAME_ILLprice_compute_dual_inf (lp, p, NULL, 0, PRIMAL_PHASEI);
+ }
+ }
+ }
+CLEANUP:
+ if (rval == QS_LP_CHANGE_PREC)
+ {
+ MESSAGE (__QS_SB_VERB, "Changing precision");
+ return rval;
+ }
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLsimplex_retest_dsolution (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * p,
+ int phase,
+ EGLPNUM_TYPENAME_feas_info * fi)
+{
+ int rval = 0;
+ int fbid = lp->fbasisid;
+ int bid = lp->basisid;
+ EGLPNUM_TYPE *ptol = &(lp->tol->pfeas_tol);
+ EGLPNUM_TYPE *dtol = &(lp->tol->dfeas_tol);
+ EGLPNUM_TYPE *iptol = &(lp->tol->ip_tol);
+ EGLPNUM_TYPE *idtol = &(lp->tol->id_tol);
+
+ //ILL_IFTRACE("\t%s:%s:%d\n",__func__,__FILE__,__LINE__);
+
+ fi->pstatus = -1;
+ fi->dstatus = -1;
+ if (fbid < bid - PARAM_DUAL_REFACTORGAP)
+ {
+ //ILL_IFTRACE("Refactor: %s:%s:%d\n",__func__,__FILE__,__LINE__);
+ rval = EGLPNUM_TYPENAME_ILLbasis_refactor (lp);
+ CHECKRVALG (rval, CLEANUP);
+ }
+ if (fbid < bid - PARAM_DUAL_RESOLVEGAP)
+ {
+ //ILL_IFTRACE("\t%s:%s:%d\n",__func__,__FILE__,__LINE__);
+ EGLPNUM_TYPENAME_ILLfct_compute_piz (lp);
+ EGLPNUM_TYPENAME_ILLfct_compute_dz (lp);
+ }
+
+ if (phase == DUAL_PHASEII)
+ {
+ //ILL_IFTRACE("\t%s:%s:%d\n",__func__,__FILE__,__LINE__);
+ if (fbid < bid - PARAM_DUAL_RESOLVEGAP)
+ {
+ //ILL_IFTRACE("\t%s:%s:%d\n",__func__,__FILE__,__LINE__);
+ EGLPNUM_TYPENAME_ILLfct_compute_xbz (lp);
+ CHECKRVALG (rval, CLEANUP);
+ if (p != NULL)
+ {
+ //ILL_IFTRACE("\t%s:%s:%d\n",__func__,__FILE__,__LINE__);
+ if (p->d_strategy == COMPLETE_PRICING)
+ {
+ //ILL_IFTRACE("\t%s:%s:%d\n",__func__,__FILE__,__LINE__);
+ EGLPNUM_TYPENAME_ILLprice_compute_primal_inf (lp, p, NULL, 0, DUAL_PHASEII);
+ }
+ else
+ {
+ //ILL_IFTRACE("\t%s:%s:%d\n",__func__,__FILE__,__LINE__);
+ EGLPNUM_TYPENAME_ILLprice_update_mpartial_price (lp, p, DUAL_PHASEII, ROW_PRICING);
+ }
+ }
+ }
+ //ILL_IFTRACE("\t%s:%s:%d\n",__func__,__FILE__,__LINE__);
+ EGLPNUM_TYPENAME_ILLfct_compute_dobj (lp);
+ EGLPNUM_TYPENAME_ILLfct_check_dfeasible (lp, fi, *dtol);
+ EGLPNUM_TYPENAME_ILLfct_check_pfeasible (lp, fi, *ptol);
+ }
+ else if (phase == DUAL_PHASEI)
+ {
+ EGLPNUM_TYPENAME_ILLfct_check_dfeasible (lp, fi, *idtol);
+ if (fi->dstatus != DUAL_FEASIBLE)
+ {
+ EGLPNUM_TYPENAME_ILLfct_compute_phaseI_xbz (lp);
+ EGLPNUM_TYPENAME_ILLfct_check_pIpfeasible (lp, fi, *iptol);
+ if (p != NULL)
+ {
+ if (p->d_strategy == COMPLETE_PRICING)
+ EGLPNUM_TYPENAME_ILLprice_compute_primal_inf (lp, p, NULL, 0, DUAL_PHASEI);
+ else
+ EGLPNUM_TYPENAME_ILLprice_update_mpartial_price (lp, p, DUAL_PHASEI, ROW_PRICING);
+ }
+ }
+ }
+CLEANUP:
+ EG_RETURN (rval);
+}
+
+int EGLPNUM_TYPENAME_ILLsimplex_solution (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPE * xz,
+ EGLPNUM_TYPE * piz,
+ EGLPNUM_TYPE * dz,
+ EGLPNUM_TYPE * objval)
+{
+ int i, j;
+ int col;
+
+ if (xz != NULL)
+ {
+ if (lp->basisstat.optimal == 0)
+ {
+ EG_RETURN (1);
+ }
+ for (i = 0; i < lp->nrows; i++)
+ EGLPNUM_TYPENAME_EGlpNumCopy (xz[lp->baz[i]], lp->xbz[i]);
+ for (j = 0; j < lp->nnbasic; j++)
+ {
+ col = lp->nbaz[j];
+ if (lp->vstat[col] == STAT_UPPER)
+ EGLPNUM_TYPENAME_EGlpNumCopy (xz[col], lp->uz[col]);
+ else if (lp->vstat[col] == STAT_LOWER)
+ EGLPNUM_TYPENAME_EGlpNumCopy (xz[col], lp->lz[col]);
+ else
+ EGLPNUM_TYPENAME_EGlpNumZero (xz[col]);
+ }
+ }
+ if (piz != NULL)
+ {
+ if (lp->basisstat.optimal == 0)
+ {
+ EG_RETURN (1);
+ }
+ for (i = 0; i < lp->nrows; i++)
+ EGLPNUM_TYPENAME_EGlpNumCopy (piz[i], lp->piz[i]);
+ }
+ if (dz != NULL)
+ {
+ if (lp->basisstat.optimal == 0)
+ {
+ EG_RETURN (1);
+ }
+ for (i = 0; i < lp->nrows; i++)
+ EGLPNUM_TYPENAME_EGlpNumZero (dz[lp->baz[i]]);
+ for (j = 0; j < lp->nnbasic; j++)
+ EGLPNUM_TYPENAME_EGlpNumCopy (dz[lp->nbaz[j]], lp->dz[j]);
+ }
+ if (objval != NULL)
+ EGLPNUM_TYPENAME_EGlpNumCopy (*objval, lp->objval);
+ return 0;
+}
+
+int EGLPNUM_TYPENAME_ILLsimplex_infcertificate (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPE * pi)
+{
+ int i, col, nz;
+ char *sense;
+ EGLPNUM_TYPE *x, *l, *u;
+ EGLPNUM_TYPENAME_lp_status_info *ls;
+
+ if (pi == NULL)
+ return 0;
+
+ ls = &(lp->basisstat);
+ if (ls->primal_infeasible == 0 && ls->dual_unbounded == 0)
+ {
+ EG_RETURN (1);
+ }
+
+ if (lp->final_phase == PRIMAL_PHASEI && lp->pIpiz != NULL)
+ {
+ for (i = 0; i < lp->nrows; i++)
+ EGLPNUM_TYPENAME_EGlpNumCopy (pi[i], lp->pIpiz[i]);
+ }
+ else if (lp->final_phase == DUAL_PHASEII && lp->infub_ix != -1)
+ {
+ col = lp->baz[lp->infub_ix];
+ x = &(lp->xbz[lp->infub_ix]);
+ l = &(lp->lz[col]);
+ u = &(lp->uz[col]);
+
+ for (i = 0; i < lp->nrows; i++)
+ EGLPNUM_TYPENAME_EGlpNumZero (pi[i]);
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (*l, EGLPNUM_TYPENAME_NINFTY) && EGLPNUM_TYPENAME_EGlpNumIsLess (*x, *l))
+ {
+ for (i = 0, nz = lp->zz.nzcnt; i < nz; i++)
+ EGLPNUM_TYPENAME_EGlpNumCopyNeg (pi[lp->zz.indx[i]], lp->zz.coef[i]);
+ }
+ else
+ {
+ for (i = 0, nz = lp->zz.nzcnt; i < nz; i++)
+ EGLPNUM_TYPENAME_EGlpNumCopy (pi[lp->zz.indx[i]], lp->zz.coef[i]);
+ }
+ }
+ else
+ {
+ QSlog("Invalid call to inf. certificate routine");
+ EG_RETURN (1);
+ }
+
+ sense = lp->O->sense;
+ for (i = 0; i < lp->nrows; i++)
+ {
+ if (sense[i] == 'G' && EGLPNUM_TYPENAME_EGlpNumIsLessZero (pi[i]))
+ EGLPNUM_TYPENAME_EGlpNumZero (pi[i]);
+ if (sense[i] == 'L' && EGLPNUM_TYPENAME_EGlpNumIsGreatZero (pi[i]))
+ EGLPNUM_TYPENAME_EGlpNumZero (pi[i]);
+ }
+ return 0;
+}
+
+#if SIMPLEX_DEBUG > 1
+static void test_cert (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPE * pi)
+{
+ int i, j;
+ int mcnt, mbeg;
+ EGLPNUM_TYPE fsum, sum;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (fsum);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (sum);
+ EGLPNUM_TYPENAME_EGlpNumZero (fsum);
+
+ for (i = 0; i < lp->nrows; i++)
+ {
+ if (lp->O->sense[i] == 'G' && EGLPNUM_TYPENAME_EGlpNumIsLessZero (pi[i]))
+ QSlog("compl");
+ if (lp->O->sense[i] == 'L' && EGLPNUM_TYPENAME_EGlpNumIsGreatZero (pi[i]))
+ QSlog("compll");
+ }
+
+ for (i = 0; i < lp->nrows; i++)
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (fsum, pi[i], lp->bz[i]);
+
+ for (j = 0; j < lp->nnbasic; j++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumZero (sum);
+ mcnt = lp->matcnt[j];
+ mbeg = lp->matbeg[j];
+ for (i = 0; i < mcnt; i++)
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (sum, pi[lp->matind[mbeg + i]], lp->matval[mbeg + i]);
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_PFEAS_TOLER, sum) &&
+ (lp->vtype[j] == VLOWER || lp->vtype[j] == VFREE))
+ QSlog("compl2");
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumSign (sum);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (EGLPNUM_TYPENAME_PFEAS_TOLER, sum) &&
+ (lp->vtype[j] == VUPPER || lp->vtype[j] == VFREE))
+ QSlog("compl1");
+ EGLPNUM_TYPENAME_EGlpNumSign (sum);
+ }
+
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (sum)
+ && (lp->vtype[j] & (VFREE | VUPPER)) == 0)
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (fsum, sum, lp->lz[j]);
+ else if (EGLPNUM_TYPENAME_EGlpNumIsGreatZero (sum)
+ && (lp->vtype[j] & (VFREE | VLOWER)) == 0)
+ EGLPNUM_TYPENAME_EGlpNumSubInnProdTo (fsum, sum, lp->uz[j]);
+ }
+ QSlog("fsum = %.8f", EGLPNUM_TYPENAME_EGlpNumToLf (fsum));
+ EGLPNUM_TYPENAME_EGlpNumClearVar (fsum);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (sum);
+}
+#endif
+
+static void save_paraminfo (
+ EGLPNUM_TYPENAME_price_info * pinf,
+ EGLPNUM_TYPENAME_iter_info * it)
+{
+ EGLPNUM_TYPENAME_param_info *pr = &(it->oldinfo);
+
+ pr->origalgo = it->algorithm;
+ pr->pphaseI = pinf->pI_price;
+ pr->pphaseII = pinf->pII_price;
+ pr->dphaseI = pinf->dI_price;
+ pr->dphaseII = pinf->dII_price;
+ pr->p_strategy = pinf->p_strategy;
+ pr->d_strategy = pinf->d_strategy;
+}
+
+static void restore_paraminfo (
+ EGLPNUM_TYPENAME_iter_info * it,
+ EGLPNUM_TYPENAME_price_info * pinf)
+{
+ EGLPNUM_TYPENAME_param_info *pr = &(it->oldinfo);
+
+ it->algorithm = pr->origalgo;
+ pinf->pI_price = pr->pphaseI;
+ pinf->pII_price = pr->pphaseII;
+ pinf->dI_price = pr->dphaseI;
+ pinf->dII_price = pr->dphaseII;
+ pinf->p_strategy = pr->p_strategy;
+ pinf->d_strategy = pr->d_strategy;
+}
+
+int EGLPNUM_TYPENAME_ILLsimplex (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int algorithm,
+ EGLPNUM_TYPENAME_ILLlp_basis * B,
+ EGLPNUM_TYPENAME_price_info * pinf,
+ int *status,
+ int sdisplay,
+ itcnt_t*itcnt)
+{
+ int phase = -1;
+ int singular = -1;
+ int rval = 0;
+ int new_price = -1;
+ EGLPNUM_TYPENAME_svector wz;
+ EGLPNUM_TYPENAME_svector updz;
+ EGLPNUM_TYPENAME_feas_info fi;
+ EGLPNUM_TYPENAME_iter_info it;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (fi.totinfeas);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (it.prevobj);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (it.objtol);
+
+ it.newphase = -1;
+ it.nextphase = -1;
+ it.nextstep = -1;
+ it.sdisplay = sdisplay;
+ it.n_pivot_fail = 0;
+ it.itercnt = 0;
+ it.n_restart = 0;
+ it.solstatus = ILL_LP_UNSOLVED;
+ it.curtime = 0;
+ it.rounds = 0;
+ EGLPNUM_TYPENAME_EGlpNumCopy (it.prevobj, EGLPNUM_TYPENAME_INFTY);
+ it.nosolve = 0;
+ it.noprog = 0;
+ EGLPNUM_TYPENAME_EGlpNumCopy (it.objtol, EGLPNUM_TYPENAME_OBJBND_TOLER);
+ it.chkobj = PARAM_MAX_NOPROG;
+ it.inner = 0;
+ it.algorithm = algorithm;
+ it.pricetype = -1;
+ it.resumeid = -1;
+ save_paraminfo (pinf, &it);
+
+#if SIMPLEX_DEBUG > 0
+ if (lp->O->nrows > 1000)
+ it.sdisplay = 1;
+#endif
+ if (status)
+ *status = QS_LP_UNSOLVED;
+
+ EGLPNUM_TYPENAME_free_internal_lpinfo (lp);
+ EGLPNUM_TYPENAME_init_internal_lpinfo (lp);
+ rval = EGLPNUM_TYPENAME_build_internal_lpinfo (lp);
+ CHECKRVALG (rval, CLEANUP);
+
+ EGLPNUM_TYPENAME_ILLsvector_init (&wz);
+ rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&wz, lp->nrows);
+ CHECKRVALG (rval, CLEANUP);
+ EGLPNUM_TYPENAME_ILLsvector_init (&updz);
+ rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&updz, lp->nrows);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (it.sdisplay)
+ {
+ char buffer[256];
+ int nonzero = 0;
+ register int i = lp->ncols;
+
+ while (i--)
+ nonzero += lp->matcnt[i];
+ sprintf (buffer, "starting EGLPNUM_TYPENAME_ILLsimplex on %s...", lp->O->probname);
+ /* depending on LP's reporter
+ * string is printed to stdout
+ * or handed to GUI */
+ rval = rval || ILLstring_report (buffer, &lp->O->reporter);
+ QSlog("Problem has %d rows and %d cols and %d nonzeros", lp->nrows,
+ lp->ncols, nonzero);
+ }
+ EGLPNUM_TYPENAME_ILLfct_set_variable_type (lp);
+
+ if (B != 0)
+ {
+ rval = EGLPNUM_TYPENAME_ILLbasis_load (lp, B);
+ CHECKRVALG (rval, CLEANUP);
+ if (it.algorithm == DUAL_SIMPLEX)
+ {
+ if (B->rownorms)
+ {
+ rval = EGLPNUM_TYPENAME_ILLprice_load_rownorms (lp, B->rownorms, pinf);
+ CHECKRVALG (rval, CLEANUP);
+ }
+ else
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (pinf->dsinfo.norms);
+ }
+ else if (it.algorithm == PRIMAL_SIMPLEX)
+ {
+ if (B->colnorms)
+ {
+ rval = EGLPNUM_TYPENAME_ILLprice_load_colnorms (lp, B->colnorms, pinf);
+ CHECKRVALG (rval, CLEANUP);
+ }
+ else
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (pinf->psinfo.norms);
+ }
+ else if (it.algorithm != PRIMAL_OR_DUAL)
+ {
+ QSlog("Unknown algorithm %d in EGLPNUM_TYPENAME_ILLsimplex", it.algorithm);
+ rval = 1;
+ ILL_CLEANUP;
+ }
+ }
+ else if (lp->basisid == -1)
+ {
+ if (lp->nrows < 200 && lp->ncols < 400)
+ rval = EGLPNUM_TYPENAME_ILLbasis_get_initial (lp, it.algorithm);
+ else
+ rval = EGLPNUM_TYPENAME_ILLbasis_get_cinitial (lp, it.algorithm);
+ CHECKRVALG (rval, CLEANUP);
+ EGLPNUM_TYPENAME_ILLprice_free_pricing_info (pinf);
+ }
+
+ if (lp->fbasisid != lp->basisid)
+ {
+ rval = EGLPNUM_TYPENAME_ILLbasis_factor (lp, &singular);
+ CHECKRVALG (rval, CLEANUP);
+ if (singular)
+ {
+ MESSAGE (__QS_SB_VERB, "Singular basis found!");
+ EGLPNUM_TYPENAME_ILLprice_free_pricing_info (pinf);
+ }
+ }
+
+START:
+#if 0
+ if (it.resumeid == SIMPLEX_RESUME_UNSHIFT)
+ QSlog("Resuming Unshift");
+ else if (it.resumeid == SIMPLEX_RESUME_SING)
+ QSlog("Resuming Singular");
+ else if (it.resumeid == SIMPLEX_RESUME_NUMER)
+ QSlog("Resuming Numer");
+ else if (it.resumeid != -1)
+ QSlog("Resuming for other reason... %d", it.resumeid);
+#endif
+ it.solstatus = ILL_LP_UNSOLVED;
+ init_lp_status_info (&(lp->basisstat));
+
+ EGLPNUM_TYPENAME_ILLfct_compute_piz (lp);
+ EGLPNUM_TYPENAME_ILLfct_compute_dz (lp);
+ if (it.algorithm == DUAL_SIMPLEX)
+ {
+ if (B != NULL || it.resumeid == SIMPLEX_RESUME_UNSHIFT)
+ EGLPNUM_TYPENAME_ILLfct_dual_adjust (lp, lp->tol->dfeas_tol);
+ else
+ EGLPNUM_TYPENAME_ILLfct_dual_adjust (lp, EGLPNUM_TYPENAME_zeroLpNum);
+ }
+ EGLPNUM_TYPENAME_ILLfct_compute_xbz (lp);
+
+ EGLPNUM_TYPENAME_ILLfct_check_pfeasible (lp, &fi, lp->tol->pfeas_tol);
+ EGLPNUM_TYPENAME_ILLfct_check_dfeasible (lp, &fi, lp->tol->dfeas_tol);
+ EGLPNUM_TYPENAME_ILLfct_set_status_values (lp, fi.pstatus, fi.dstatus, PHASEII, PHASEII);
+
+ if (fi.dstatus == DUAL_FEASIBLE && EGLPNUM_TYPENAME_EGlpNumIsNeqq (lp->objbound, EGLPNUM_TYPENAME_INFTY))
+ {
+ EGLPNUM_TYPENAME_ILLfct_compute_dobj (lp);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (lp->objbound, lp->dobjval))
+ {
+ it.solstatus = ILL_BND_REACHED;
+ QSlog("solstatus = ILL_BND_REACHED = 5 %lf %lf",
+ EGLPNUM_TYPENAME_EGlpNumToLf (lp->objbound),
+ EGLPNUM_TYPENAME_EGlpNumToLf (lp->dobjval));
+ goto TERMINATE;
+ }
+ }
+ if (fi.pstatus == PRIMAL_FEASIBLE && fi.dstatus == DUAL_FEASIBLE)
+ {
+ it.solstatus = ILL_LP_SOLVED;
+ EGLPNUM_TYPENAME_ILLfct_compute_pobj (lp);
+ goto TERMINATE;
+ }
+
+ if (it.algorithm == PRIMAL_OR_DUAL)
+ {
+ if (fi.pstatus == PRIMAL_FEASIBLE)
+ it.algorithm = PRIMAL_SIMPLEX;
+ else if (fi.dstatus == DUAL_FEASIBLE)
+ it.algorithm = DUAL_SIMPLEX;
+ else if (EGLPNUM_TYPENAME_EGlpNumToLf (lp->pinfeas) < 10 * EGLPNUM_TYPENAME_EGlpNumToLf (lp->dinfeas))
+ it.algorithm = PRIMAL_SIMPLEX;
+ else
+ it.algorithm = DUAL_SIMPLEX;
+ }
+
+ if (it.algorithm == PRIMAL_SIMPLEX)
+ {
+ if (fi.pstatus == PRIMAL_FEASIBLE)
+ phase = PRIMAL_PHASEII;
+ else
+ phase = PRIMAL_PHASEI;
+ }
+ else if (it.algorithm == DUAL_SIMPLEX)
+ {
+ if (fi.dstatus == DUAL_FEASIBLE)
+ phase = DUAL_PHASEII;
+ else
+ phase = DUAL_PHASEI;
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLprice_build_pricing_info (lp, pinf, phase);
+ CHECKRVALG (rval, CLEANUP);
+
+ it.newphase = SIMPLEX_PHASE_NEW;
+ it.nextstep = SIMPLEX_CONTINUE;
+
+ while (it.nextstep == SIMPLEX_CONTINUE)
+ {
+ //ILL_IFTRACE("\t%s:%s:%d\n",__func__,__FILE__,__LINE__);
+
+ if (phase == PRIMAL_PHASEI)
+ {
+ rval = primal_phaseI_step (lp, pinf, &updz, &wz, &it);
+ CHECKRVALG (rval, CLEANUP);
+ }
+
+ else if (phase == PRIMAL_PHASEII)
+ {
+ rval = primal_phaseII_step (lp, pinf, &updz, &wz, &it);
+ CHECKRVALG (rval, CLEANUP);
+ }
+
+ else if (phase == DUAL_PHASEI)
+ {
+ rval = dual_phaseI_step (lp, pinf, &updz, &wz, &it);
+ CHECKRVALG (rval, CLEANUP);
+ }
+
+ else if (phase == DUAL_PHASEII)
+ {
+ rval = dual_phaseII_step (lp, pinf, &updz, &wz, &it);
+ CHECKRVALG (rval, CLEANUP);
+ }
+ if (it.nextstep == SIMPLEX_RESUME)
+ {
+ //ILL_IFTRACE("\t%s:%s:%d\n",__func__,__FILE__,__LINE__);
+ EGLPNUM_TYPENAME_ILLprice_free_pricing_info (pinf);
+ if (it.resumeid == SIMPLEX_RESUME_UNSHIFT)
+ {
+ if (it.pricetype == QS_PRICE_PDEVEX)
+ {
+ pinf->pI_price = QS_PRICE_PDEVEX;
+ pinf->pII_price = QS_PRICE_PDEVEX;
+ }
+ else if (it.pricetype == QS_PRICE_DDEVEX)
+ {
+ pinf->dI_price = QS_PRICE_DDEVEX;
+ pinf->dII_price = QS_PRICE_DDEVEX;
+ }
+ }
+ else if (it.resumeid == SIMPLEX_RESUME_NUMER)
+ {
+ EGLPNUM_TYPENAME_ILLfct_unroll_bound_change (lp);
+ EGLPNUM_TYPENAME_ILLfct_unroll_coef_change (lp);
+ /* we are disabling re-do under this circunstances ! */
+ rval = EGLPNUM_TYPENAME_ILLbasis_get_initial (lp, it.algorithm);
+ CHECKRVALG (rval, CLEANUP);
+ rval = EGLPNUM_TYPENAME_ILLbasis_factor (lp, &singular);
+ if (singular)
+ MESSAGE (__QS_SB_VERB, "Singular basis found!");
+ CHECKRVALG (rval, CLEANUP);
+ }
+ it.pricetype = -1;
+ if (it.n_restart > SIMPLEX_MAX_RESTART)
+ {
+ it.solstatus = ILL_MAX_ITER;
+ goto LIMIT_TERMINATE;
+ }
+ goto START;
+ }
+ else if (it.nextstep == SIMPLEX_CONTINUE)
+ {
+ //ILL_IFTRACE("\t%s:%s:%d\n",__func__,__FILE__,__LINE__);
+ it.itercnt++;
+
+ if (it.nextphase != phase)
+ {
+ //ILL_IFTRACE("\t%s:%s:%d\n",__func__,__FILE__,__LINE__);
+ it.newphase = SIMPLEX_PHASE_NEW;
+ phase = it.nextphase;
+ new_price = EGLPNUM_TYPENAME_ILLprice_get_price (pinf, phase);
+
+ if (pinf->cur_price != new_price)
+ {
+ //ILL_IFTRACE("\t%s:%s:%d\n",__func__,__FILE__,__LINE__);
+ EGLPNUM_TYPENAME_ILLprice_free_pricing_info (pinf);
+ rval = EGLPNUM_TYPENAME_ILLprice_build_pricing_info (lp, pinf, phase);
+ CHECKRVALG (rval, CLEANUP);
+ }
+ }
+ }
+ }
+
+#if SIMPLEX_DEBUG > 0
+ EGLPNUM_TYPENAME_ILLfct_print_counts (lp);
+#endif
+LIMIT_TERMINATE:
+ rval = terminate_simplex (lp, phase, &it);
+ CHECKRVALG (rval, CLEANUP);
+
+TERMINATE:
+ restore_paraminfo (&it, pinf);
+
+ if (it.sdisplay)
+ {
+ QSlog("completed EGLPNUM_TYPENAME_ILLsimplex");
+ QSlog("%s: ", lp->O->probname);
+ }
+
+ if (status)
+ {
+ if (it.solstatus == ILL_MAX_ITER)
+ {
+ *status = QS_LP_ITER_LIMIT;
+ }
+ else if (it.solstatus == ILL_MAX_TIME)
+ {
+ *status = QS_LP_TIME_LIMIT;
+ }
+ else if (it.solstatus == ILL_LP_ABORTED)
+ {
+ *status = QS_LP_ABORTED;
+ }
+ else if (it.solstatus == ILL_PPHASEI_ERROR ||
+ it.solstatus == ILL_PPHASEII_ERROR ||
+ it.solstatus == ILL_DPHASEI_ERROR ||
+ it.solstatus == ILL_DPHASEII_ERROR)
+ {
+ *status = QS_LP_NUMERR;
+ }
+ else if(it.solstatus == ILL_LP_UNSOLVED)
+ {
+ *status = QS_LP_UNSOLVED;
+ }
+ else if (it.solstatus == ILL_BND_REACHED)
+ {
+ *status = QS_LP_OBJ_LIMIT;
+ }
+ else if (it.solstatus == ILL_LP_SOLVED)
+ {
+ if (lp->basisstat.optimal)
+ {
+ *status = QS_LP_OPTIMAL;
+ }
+ else if (lp->basisstat.primal_infeasible || lp->basisstat.dual_unbounded)
+ {
+ *status = QS_LP_INFEASIBLE;
+ if (it.sdisplay)
+ {
+ if (lp->basisstat.primal_infeasible)
+ QSlog("Primal Infeasible");
+ else
+ QSlog("Dual Unbounded");
+ }
+ }
+ else if (lp->basisstat.primal_unbounded)
+ {
+ *status = QS_LP_UNBOUNDED;
+ }
+ }
+ else
+ {
+ QSlog("unknown solution status in EGLPNUM_TYPENAME_ILLsimplex %d",
+ it.solstatus);
+ rval = 1;
+ CHECKRVALG (rval, CLEANUP);
+ }
+ }
+
+#if SIMPLEX_DEBUG > 1
+ {
+ int rva = 0;
+ EGLPNUM_TYPE *pi = NULL;
+
+ pi = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+ rva = EGLPNUM_TYPENAME_ILLsimplex_infcertificate (lp, pi);
+ QSlog("rva = %d", rva);
+ if (!rva)
+ {
+ test_cert (lp, pi);
+ }
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (pi);
+ }
+#endif
+ /* update counter */
+ itcnt->pI_iter += lp->cnts->pI_iter;
+ itcnt->pII_iter += lp->cnts->pII_iter;
+ itcnt->dI_iter += lp->cnts->dI_iter;
+ itcnt->dII_iter += lp->cnts->dII_iter;
+ itcnt->tot_iter = itcnt->pI_iter + itcnt->pII_iter + itcnt->dI_iter +
+ itcnt->dII_iter;
+ /* end update */
+ if (it.sdisplay)
+ {
+ int bstat = 0;
+
+ QSlog("time = %.3f, pI = %d, pII = %d, dI = %d, dII = %d,",
+ ILLutil_zeit () - lp->starttime, lp->cnts->pI_iter,
+ lp->cnts->pII_iter, lp->cnts->dI_iter, lp->cnts->dII_iter);
+ get_current_stat (&(lp->basisstat), it.algorithm, &bstat);
+ switch (bstat)
+ {
+ case OPTIMAL:
+ QSlog("opt = %f", EGLPNUM_TYPENAME_EGlpNumToLf (lp->objval));
+ break;
+ case PRIMAL_INFEASIBLE:
+ QSlog("no primal soln");
+ break;
+ case PRIMAL_UNBOUNDED:
+ QSlog("primal unbounded");
+ break;
+ case PRIMAL_FEASIBLE:
+ QSlog("primal obj = %f", EGLPNUM_TYPENAME_EGlpNumToLf (lp->pobjval));
+ break;
+ case DUAL_INFEASIBLE:
+ QSlog("no dual soln");
+ break;
+ case DUAL_UNBOUNDED:
+ QSlog("dual unbounded");
+ break;
+ case DUAL_FEASIBLE:
+ QSlog("dual obj = %f", EGLPNUM_TYPENAME_EGlpNumToLf (lp->dobjval));
+ break;
+ }
+
+ if (it.sdisplay > 1)
+ {
+ if (it.algorithm == PRIMAL_SIMPLEX && pinf->pI_price == QS_PRICE_PDEVEX)
+ QSlog("Devex norms initialised %d times", pinf->pdinfo.ninit);
+ }
+ }
+
+CLEANUP:
+ EGLPNUM_TYPENAME_ILLsvector_free (&wz);
+ EGLPNUM_TYPENAME_ILLsvector_free (&updz);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (it.prevobj);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (it.objtol);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (fi.totinfeas);
+ if (rval == QS_LP_CHANGE_PREC)
+ {
+ MESSAGE (__QS_SB_VERB, "Changing precision");
+ return rval;
+ }
+ else
+ {
+ MESSAGE (rval ? 0 : 1000, "Error code %d", rval);
+ EG_RETURN (rval);
+ }
+}
+
+static int terminate_simplex (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ int phase,
+ EGLPNUM_TYPENAME_iter_info * it)
+{
+ int rval = 0;
+ int sphase;
+ EGLPNUM_TYPENAME_feas_info fi;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (fi.totinfeas);
+
+ if (it->solstatus != ILL_MAX_TIME && it->solstatus != ILL_MAX_ITER)
+ ILL_CLEANUP;
+
+ if (it->algorithm == PRIMAL_SIMPLEX)
+ {
+ if (lp->nbchange != 0)
+ {
+ if (it->sdisplay > 1)
+ {
+ QSlog("unrolling %d bound shifts", lp->nbchange);
+ }
+ EGLPNUM_TYPENAME_ILLfct_unroll_bound_change (lp);
+ }
+ rval = EGLPNUM_TYPENAME_ILLsimplex_retest_psolution (lp, NULL, phase, &fi);
+ CHECKRVALG (rval, CLEANUP);
+
+ sphase = (phase == PRIMAL_PHASEI) ? PHASEI : PHASEII;
+ EGLPNUM_TYPENAME_ILLfct_set_status_values (lp, fi.pstatus, fi.dstatus, PHASEII, sphase);
+ }
+ else if (it->algorithm == DUAL_SIMPLEX)
+ {
+ if (lp->ncchange != 0)
+ {
+ if (it->sdisplay > 1)
+ {
+ QSlog("unrolling %d coef shifts", lp->ncchange);
+ }
+ EGLPNUM_TYPENAME_ILLfct_unroll_coef_change (lp);
+ }
+ rval = EGLPNUM_TYPENAME_ILLsimplex_retest_dsolution (lp, NULL, phase, &fi);
+ CHECKRVALG (rval, CLEANUP);
+
+ sphase = (phase == DUAL_PHASEI) ? PHASEI : PHASEII;
+ EGLPNUM_TYPENAME_ILLfct_set_status_values (lp, fi.pstatus, fi.dstatus, sphase, PHASEII);
+ }
+
+CLEANUP:
+ EGLPNUM_TYPENAME_EGlpNumClearVar (fi.totinfeas);
+ EG_RETURN (rval);
+}
+
+static int test_progress (
+ EGLPNUM_TYPE objval,
+ EGLPNUM_TYPE prevobj)
+{
+ EGLPNUM_TYPE denom;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (denom);
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (denom, objval, prevobj);
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (objval, EGLPNUM_TYPENAME_PROGRESS_ZERO))
+ EGLPNUM_TYPENAME_EGlpNumDivTo (denom, objval);
+ if (!EGLPNUM_TYPENAME_EGlpNumIsNeqZero (denom, EGLPNUM_TYPENAME_PROGRESS_THRESH))
+ {
+ EGLPNUM_TYPENAME_EGlpNumClearVar (denom);
+ return 0;
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumClearVar (denom);
+ return 1;
+ }
+}
+
+static void monitor_iter (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * p,
+ EGLPNUM_TYPENAME_iter_info * it,
+ int phase)
+{
+ EGLPNUM_TYPE print_val;
+ double tottime = ILLutil_zeit () - lp->starttime;
+ int curtime = ILLutil_our_floor (tottime); /* MONIKA */
+ char print_str[20];
+ EGLPNUM_TYPENAME_feas_info fi;
+ int aborted = 0;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (print_val);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (fi.totinfeas);
+ EGLPNUM_TYPENAME_EGlpNumZero (fi.totinfeas);
+ EGLPNUM_TYPENAME_EGlpNumZero (print_val);
+
+ /* one of the following two time display mechanisms */
+ switch (phase)
+ {
+ case PRIMAL_PHASEI:
+ EGLPNUM_TYPENAME_EGlpNumCopy (print_val, lp->pinfeas);
+ EGLPNUM_TYPENAME_EGlpNumAddTo (fi.totinfeas, lp->pinfeas);
+ strcpy (print_str, "primal infeas");
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (lp->pinfeas) &&
+ (EGLPNUM_TYPENAME_EGlpNumIsNeqZero (lp->pinfeas, EGLPNUM_TYPENAME_oneLpNum)))
+ {
+ /*QSlog("Negative Infeasibility! Imposible %lg %la, iter %d",
+ * EGLPNUM_TYPENAME_EGlpNumToLf (print_val), EGLPNUM_TYPENAME_EGlpNumToLf (print_val), it->itercnt);
+ */
+ //exit(1);
+ }
+ break;
+ case PRIMAL_PHASEII:
+ EGLPNUM_TYPENAME_EGlpNumCopy (print_val, lp->pobjval);
+ strcpy (print_str, "primal objval");
+ break;
+ case DUAL_PHASEI:
+ EGLPNUM_TYPENAME_EGlpNumCopy (print_val, lp->dinfeas);
+ EGLPNUM_TYPENAME_EGlpNumAddTo (fi.totinfeas, lp->dinfeas);
+ strcpy (print_str, "dual infeas");
+ break;
+ case DUAL_PHASEII:
+ EGLPNUM_TYPENAME_EGlpNumCopy (print_val, lp->dobjval);
+ strcpy (print_str, "dual objval");
+ break;
+ }
+
+ aborted = report_value (lp, it, print_str, print_val);
+ /*if (it->sdisplay && it->itercnt % lp->iterskip == 0) {
+ * // QSlog("(%d): %s = %f", it->itercnt, print_str, print_val);
+ * } */
+ if (curtime != it->curtime)
+ {
+ it->curtime = curtime;
+ /*
+ * if (it->sdisplay){
+ * QSlog("time = %d.0, ", curtime);
+ * QSlog("(%d): %s = %f", it->itercnt, print_str, print_val);
+ * }
+ */
+ }
+
+ EGLPNUM_TYPENAME_EGlpNumAddUiTo (fi.totinfeas, 1000);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (fi.totinfeas))
+ {
+ it->nextstep = SIMPLEX_TERMINATE;
+ it->solstatus = ILL_MAX_ITER;
+ MESSAGE (it->sdisplay ? 0 : __QS_SB_VERB,
+ "early finish by excess infeasibility");
+ ILL_CLEANUP;
+ }
+
+ if (phase == DUAL_PHASEII && EGLPNUM_TYPENAME_EGlpNumIsNeqq (lp->objbound, EGLPNUM_TYPENAME_INFTY))
+ {
+ /*if (lp->dobjval > lp->objbound + it->objtol) */
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (print_val, lp->dobjval, lp->objbound);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (it->objtol, print_val))
+ {
+ EGLPNUM_TYPENAME_ILLfct_unroll_coef_change (lp);
+ EGLPNUM_TYPENAME_ILLfct_check_dfeasible (lp, &fi, lp->tol->dfeas_tol);
+ EGLPNUM_TYPENAME_ILLfct_set_status_values (lp, -1, fi.dstatus, -1, PHASEII);
+
+ if (fi.dstatus == DUAL_FEASIBLE)
+ {
+ EGLPNUM_TYPENAME_ILLfct_compute_dobj (lp);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (lp->objbound, lp->dobjval))
+ {
+ it->solstatus = ILL_BND_REACHED;
+ it->nextstep = SIMPLEX_TERMINATE;
+ /*if (it->sdisplay) */
+ {
+ QSlog("bound reached %lf %lf", EGLPNUM_TYPENAME_EGlpNumToLf (lp->objbound),
+ EGLPNUM_TYPENAME_EGlpNumToLf (lp->dobjval));
+ }
+ }
+ else
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (it->objtol, 10);
+ }
+ else
+ {
+ it->nextphase = DUAL_PHASEI;
+ it->newphase = SIMPLEX_PHASE_NEW;
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (it->objtol, 5);
+ }
+ }
+ }
+ if (it->itercnt >= lp->maxiter)
+ {
+ it->solstatus = ILL_MAX_ITER;
+ it->nextstep = SIMPLEX_TERMINATE;
+ if (it->sdisplay)
+ {
+ QSlog("iter limit reached");
+ }
+ ILL_CLEANUP;
+ }
+ else if (tottime >= lp->maxtime)
+ {
+ it->solstatus = ILL_MAX_TIME;
+ it->nextstep = SIMPLEX_TERMINATE;
+ if (it->sdisplay)
+ {
+ QSlog("time limit reached");
+ }
+ ILL_CLEANUP;
+ }
+ else if (aborted)
+ {
+ it->solstatus = ILL_LP_ABORTED;
+ it->nextstep = SIMPLEX_TERMINATE;
+ if (it->sdisplay)
+ {
+ QSlog("aborted");
+ }
+ ILL_CLEANUP;
+ }
+ /* why is this commented out? */
+ if(0){
+ if (it->rounds && it->inner){
+ it->inner --;
+ if (it->inner == 0){
+ QSlog("restoring ..");
+ restore_paraminfo (it, p);
+ it->newphase = SIMPLEX_PHASE_NEW;
+ it->nextstep = SIMPLEX_RESUME;
+ /*it->resumeid = SIMPLEX_RESUME_OUTER;*/
+ ILL_CLEANUP;
+ }
+ }
+ }
+ if (phase == DUAL_PHASEII)
+ {
+ if (it->noprog > it->chkobj)
+ {
+ EGLPNUM_TYPENAME_ILLfct_perturb_coefs (lp);
+ it->noprog = 0;
+ EGLPNUM_TYPENAME_EGlpNumCopy (it->prevobj, lp->dobjval);
+ }
+ }
+ else if (phase == PRIMAL_PHASEII)
+ {
+ if (it->noprog > it->chkobj)
+ {
+ EGLPNUM_TYPENAME_ILLfct_perturb_bounds (lp);
+ it->noprog = 0;
+ EGLPNUM_TYPENAME_EGlpNumCopy (it->prevobj, lp->pobjval);
+ }
+ }
+ else if (phase == PRIMAL_PHASEI)
+ {
+ if (it->noprog > it->chkobj)
+ {
+ it->algorithm = DUAL_SIMPLEX;
+ it->nextstep = SIMPLEX_RESUME;
+ it->resumeid = SIMPLEX_RESUME_NUMER;
+ /* this is to force to exit in the case of bad basis */
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->pfeas_tol, SIMPLEX_FACTOR);
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->dfeas_tol, SIMPLEX_FACTOR);
+ it->n_restart++;
+ //QSlog("Resume Numerical %s:%s:%d",__func__,__FILE__,__LINE__);
+ }
+ }
+ else if (phase == DUAL_PHASEI)
+ {
+ if (it->noprog > it->chkobj)
+ {
+ it->algorithm = PRIMAL_SIMPLEX;
+ it->nextstep = SIMPLEX_RESUME;
+ it->resumeid = SIMPLEX_RESUME_NUMER;
+ /* this is to force to exit in the case of bad basis */
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->pfeas_tol, SIMPLEX_FACTOR);
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->dfeas_tol, SIMPLEX_FACTOR);
+ it->n_restart++;
+ //QSlog("Resume Numerical %s:%s:%d",__func__,__FILE__,__LINE__);
+ }
+ }
+CLEANUP:
+ EGLPNUM_TYPENAME_EGlpNumClearVar (fi.totinfeas);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (print_val);
+ return;
+}
+
+static int primal_phaseI_step (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * pinf,
+ EGLPNUM_TYPENAME_svector * updz,
+ EGLPNUM_TYPENAME_svector * wz,
+ EGLPNUM_TYPENAME_iter_info * it)
+{
+ int rval = 0;
+ int singular = 0;
+ int refactor = 0;
+ int cphase = PRIMAL_PHASEI;
+ EGLPNUM_TYPE alpha;
+ EGLPNUM_TYPENAME_feas_info fi;
+ EGLPNUM_TYPENAME_ratio_res rs;
+ EGLPNUM_TYPENAME_price_res pr;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (alpha);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (fi.totinfeas);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (pr.dinfeas);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (pr.pinfeas);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (rs.tz);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (rs.lbound);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (rs.ecoeff);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (rs.pivotval);
+ EGLPNUM_TYPENAME_EGlpNumZero (alpha);
+
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_PPHASE1ITER, 0, EGLPNUM_TYPENAME_zeroLpNum);
+ it->nextstep = SIMPLEX_CONTINUE;
+ it->nextphase = PRIMAL_PHASEI;
+ lp->final_phase = PRIMAL_PHASEI;
+ it->nosolve++;
+
+ if (it->newphase != 0)
+ {
+ EGLPNUM_TYPENAME_ILLfct_check_pfeasible (lp, &fi, lp->tol->ip_tol);
+ if (it->newphase == SIMPLEX_PHASE_NEW)
+ {
+ it->noprog = 0;
+ if (it->sdisplay)
+ {
+ QSlog("starting primal phase I, nosolve %d", it->nosolve);
+ }
+ }
+ it->newphase = 0;
+ it->nosolve = 0;
+ EGLPNUM_TYPENAME_EGlpNumCopy (it->prevobj, lp->pinfeas);
+ lp->pIpiz = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nrows);
+ lp->pIdz = EGLPNUM_TYPENAME_EGlpNumAllocArray (lp->nnbasic);
+
+ EGLPNUM_TYPENAME_ILLfct_compute_phaseI_piz (lp);
+ if (pinf->p_strategy == COMPLETE_PRICING)
+ {
+ EGLPNUM_TYPENAME_ILLfct_compute_phaseI_dz (lp);
+#if USEHEAP > 0
+ EGLPNUM_TYPENAME_ILLprice_free_heap (pinf);
+#endif
+ EGLPNUM_TYPENAME_ILLprice_compute_dual_inf (lp, pinf, NULL, 0, PRIMAL_PHASEI);
+#if USEHEAP > 0
+ rval = EGLPNUM_TYPENAME_ILLprice_test_for_heap (lp, pinf, lp->nnbasic, pinf->d_scaleinf,
+ PRIMAL_SIMPLEX, 0);
+ CHECKRVALG (rval, CLEANUP);
+#endif
+ }
+ else if (pinf->p_strategy == MULTI_PART_PRICING)
+ EGLPNUM_TYPENAME_ILLprice_init_mpartial_price (lp, pinf, cphase, COL_PRICING);
+ }
+
+ monitor_iter (lp, pinf, it, cphase);
+ if (it->nextstep == SIMPLEX_TERMINATE || it->nextstep == SIMPLEX_RESUME ||
+ it->newphase != 0)
+ ILL_CLEANUP;
+
+ EGLPNUM_TYPENAME_ILLprice_primal (lp, pinf, &pr, cphase);
+ ILL_IFTRACE2 ("%s:after_price\n", __func__);
+
+ if (pr.price_stat == PRICE_OPTIMAL)
+ {
+ if (it->sdisplay > 1)
+ {
+ QSlog("primal phase I seemingly done");
+ QSlog("retesting soln");
+ }
+ rval = EGLPNUM_TYPENAME_ILLsimplex_retest_psolution (lp, pinf, cphase, &fi);
+
+ CHECKRVALG (rval, CLEANUP);
+ EGLPNUM_TYPENAME_ILLfct_set_status_values (lp, fi.pstatus, fi.dstatus, PHASEII, PHASEI);
+
+ if (fi.pstatus == PRIMAL_FEASIBLE)
+ {
+ it->nextphase = PRIMAL_PHASEII;
+ }
+ else if (fi.dstatus == DUAL_FEASIBLE)
+ {
+ it->solstatus = ILL_LP_SOLVED;
+ it->nextstep = SIMPLEX_TERMINATE;
+ }
+ ILL_CLEANUP;
+ }
+
+ EGLPNUM_TYPENAME_ILLfct_compute_yz (lp, &(lp->yjz), updz, lp->nbaz[pr.eindex]);
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_YNZ, lp->yjz.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_UPNZ, updz->nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+
+ EGLPNUM_TYPENAME_ILLratio_pI_test (lp, pr.eindex, pr.dir, &rs);
+ //ILL_IFTRACE(":%d",rs.lindex);
+
+ if (rs.ratio_stat == RATIO_FAILED)
+ {
+ /*
+ * rval = E_SIMPLEX_ERROR;
+ * it->solstatus = ILL_PPHASEI_ERROR;
+ */
+ //ILL_IFTRACE("ratio_failed\n");
+ it->algorithm = DUAL_SIMPLEX;
+ it->nextstep = SIMPLEX_RESUME;
+ it->resumeid = SIMPLEX_RESUME_NUMER;
+ /* this is to force to exit in the case of bad basis */
+ it->n_restart++;
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->pfeas_tol, SIMPLEX_FACTOR);
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->dfeas_tol, SIMPLEX_FACTOR);
+ //QSlog("Resume Numerical %s:%s:%d",__func__,__FILE__,__LINE__);
+ ILL_CLEANUP;
+ }
+ else if (rs.ratio_stat == RATIO_NEGATIVE)
+ {
+ EGLPNUM_TYPE itol;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (itol);
+ //ILL_IFTRACE("ratio_negative\n");
+ EGLPNUM_TYPENAME_EGlpNumCopy (itol, lp->tol->ip_tol);
+ EGLPNUM_TYPENAME_EGlpNumZero (lp->tol->ip_tol);
+ EGLPNUM_TYPENAME_EGlpNumAddTo (lp->pinfeas, lp->upd.c_obj);
+ if (!test_progress (lp->pinfeas, it->prevobj))
+ it->noprog++;
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (it->prevobj, lp->pinfeas);
+ it->noprog = 0;
+ }
+ EGLPNUM_TYPENAME_ILLfct_update_pfeas (lp, rs.lindex, &(lp->srhs));
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->tol->ip_tol, itol);
+ EGLPNUM_TYPENAME_ILLfct_compute_ppIzz (lp, &(lp->srhs), &(lp->ssoln));
+ EGLPNUM_TYPENAME_ILLfct_update_ppI_prices (lp, pinf, &(lp->srhs), &(lp->ssoln), pr.eindex,
+ rs.lindex, EGLPNUM_TYPENAME_zeroLpNum);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (itol);
+ }
+ else if (rs.ratio_stat == RATIO_NOBCHANGE)
+ {
+ //ILL_IFTRACE("ratio_nobchange\n");
+ EGLPNUM_TYPENAME_EGlpNumAddTo (lp->pinfeas, lp->upd.c_obj);
+ if (!test_progress (lp->pinfeas, it->prevobj))
+ it->noprog++;
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (it->prevobj, lp->pinfeas);
+ it->noprog = 0;
+ }
+
+ //ILL_IFTRACE("%s:a\n",__func__);
+ EGLPNUM_TYPENAME_ILLfct_update_xz (lp, rs.tz, pr.eindex, rs.lindex);
+ EGLPNUM_TYPENAME_ILLfct_update_pfeas (lp, rs.lindex, &(lp->srhs));
+ EGLPNUM_TYPENAME_ILLfct_compute_ppIzz (lp, &(lp->srhs), &(lp->ssoln));
+ EGLPNUM_TYPENAME_ILLfct_update_basis_info (lp, pr.eindex, rs.lindex, rs.lvstat);
+#if DENSE_PI > 0
+ EGLPNUM_TYPENAME_fct_test_workvector (lp);
+ EGLPNUM_TYPENAME_fct_test_pfeasible (lp);
+#endif
+ EGLPNUM_TYPENAME_ILLfct_update_ppI_prices (lp, pinf, &(lp->srhs), &(lp->ssoln), pr.eindex,
+ rs.lindex, EGLPNUM_TYPENAME_zeroLpNum);
+ }
+ else if (rs.ratio_stat == RATIO_BCHANGE)
+ {
+ //ILL_IFTRACE("ratio_bchange\n");
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (alpha, lp->pIdz[pr.eindex], rs.pivotval);
+ EGLPNUM_TYPENAME_EGlpNumAddTo (lp->pinfeas, lp->upd.c_obj);
+
+ if (!test_progress (lp->pinfeas, it->prevobj))
+ {
+ if (lp->vtype[lp->nbaz[pr.eindex]] == VFREE ||
+ lp->vtype[lp->baz[rs.lindex]] == VARTIFICIAL)
+ {
+ if (it->noprog > 0)
+ it->noprog--;
+ }
+ else
+ it->noprog++;
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (it->prevobj, lp->pinfeas);
+ it->noprog = 0;
+ }
+
+ EGLPNUM_TYPENAME_ILLfct_compute_zz (lp, &(lp->zz), rs.lindex);
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_ZNZ, lp->zz.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+ if (pinf->p_strategy == COMPLETE_PRICING)
+ {
+ //ILL_IFTRACE("%s:a\n",__func__);
+ EGLPNUM_TYPENAME_ILLfct_compute_zA (lp, &(lp->zz), &(lp->zA));
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_ZANZ, lp->zA.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+
+ if (pinf->pI_price == QS_PRICE_PSTEEP)
+ {
+ EGLPNUM_TYPENAME_ILLfct_compute_psteep_upv (lp, wz);
+ }
+ }
+
+ rval =
+ EGLPNUM_TYPENAME_ILLprice_update_pricing_info (lp, pinf, cphase, wz, pr.eindex, rs.lindex,
+ rs.pivotval);
+ CHECKRVALG (rval, CLEANUP);
+
+ //ILL_IFTRACE("%s:b:%d\n",__func__,rs.lindex);
+ EGLPNUM_TYPENAME_ILLfct_update_xz (lp, rs.tz, pr.eindex, rs.lindex);
+ EGLPNUM_TYPENAME_ILLfct_update_pfeas (lp, rs.lindex, &(lp->srhs));
+ //ILL_IFTRACE("%s:%d:%d\n",__func__,rs.lindex,lp->srhs.nzcnt);
+ EGLPNUM_TYPENAME_ILLfct_compute_ppIzz (lp, &(lp->srhs), &(lp->ssoln));
+ EGLPNUM_TYPENAME_ILLfct_update_basis_info (lp, pr.eindex, rs.lindex, rs.lvstat);
+#if DENSE_PI > 0
+ EGLPNUM_TYPENAME_fct_test_workvector (lp);
+ EGLPNUM_TYPENAME_fct_test_pfeasible (lp);
+#endif
+ rval = EGLPNUM_TYPENAME_ILLbasis_update (lp, updz, rs.lindex, &refactor, &singular);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (singular)
+ {
+ it->nextstep = SIMPLEX_RESUME;
+ it->resumeid = SIMPLEX_RESUME_SING;
+ /* this is to force to exit in the case of bad basis */
+ it->n_restart++;
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->pfeas_tol, SIMPLEX_FACTOR);
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->dfeas_tol, SIMPLEX_FACTOR);
+ //QSlog("Resume Singular %s:%s:%d",__func__,__FILE__,__LINE__);
+ ILL_CLEANUP;
+ }
+ if (!refactor)
+ {
+ EGLPNUM_TYPENAME_ILLfct_update_ppI_prices (lp, pinf, &(lp->srhs), &(lp->ssoln), pr.eindex,
+ rs.lindex, alpha);
+ }
+ if (refactor != 0 || it->nosolve > PARAM_MAX_NOSOLVE)
+ {
+ EGLPNUM_TYPENAME_ILLfct_compute_xbz (lp);
+ EGLPNUM_TYPENAME_ILLfct_check_pfeasible (lp, &fi, lp->tol->ip_tol);
+ EGLPNUM_TYPENAME_ILLfct_set_status_values (lp, fi.pstatus, -1, PHASEII, -1);
+ if (fi.pstatus == PRIMAL_FEASIBLE)
+ it->nextphase = PRIMAL_PHASEII;
+
+ it->newphase = SIMPLEX_PHASE_RECOMP;
+ ILL_CLEANUP;
+ }
+ }
+
+#if DENSE_PI > 1
+ EGLPNUM_TYPENAME_fct_test_workvector (lp);
+ fct_test_pi_dz (lp, pinf);
+#endif
+
+CLEANUP:
+ if (it->nextphase != PRIMAL_PHASEI || it->nextstep == SIMPLEX_RESUME ||
+ it->newphase != 0 || rval != 0)
+ {
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->pIpiz);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (lp->pIdz);
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (alpha);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (fi.totinfeas);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (pr.dinfeas);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (pr.pinfeas);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (rs.tz);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (rs.lbound);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (rs.ecoeff);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (rs.pivotval);
+ //EG_RETURN(rval);
+ return rval;
+}
+
+static int primal_phaseII_step (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * pinf,
+ EGLPNUM_TYPENAME_svector * updz,
+ EGLPNUM_TYPENAME_svector * wz,
+ EGLPNUM_TYPENAME_iter_info * it)
+{
+ int boundch;
+ int rval = 0;
+ int bndtype = 0;
+ int singular = 0;
+ int refactor = 0;
+ int ratio_iter = 0;
+ int cphase = PRIMAL_PHASEII;
+ EGLPNUM_TYPE lbound;
+ EGLPNUM_TYPE alpha;
+ EGLPNUM_TYPENAME_feas_info fi;
+ EGLPNUM_TYPENAME_ratio_res rs;
+ EGLPNUM_TYPENAME_price_res pr;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (alpha);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (lbound);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (fi.totinfeas);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (pr.dinfeas);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (pr.pinfeas);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (rs.tz);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (rs.lbound);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (rs.ecoeff);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (rs.pivotval);
+
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_PPHASE2ITER, 0, EGLPNUM_TYPENAME_zeroLpNum);
+ it->nextstep = SIMPLEX_CONTINUE;
+ it->nextphase = PRIMAL_PHASEII;
+ lp->final_phase = PRIMAL_PHASEII;
+ it->nosolve++;
+
+ if (it->newphase != 0)
+ {
+ EGLPNUM_TYPENAME_ILLfct_compute_pobj (lp);
+ if (it->newphase == SIMPLEX_PHASE_NEW)
+ {
+ it->noprog = 0;
+ if (it->sdisplay)
+ {
+ QSlog("starting primal phase II, nosolve %d", it->nosolve);
+ }
+ }
+ it->newphase = 0;
+ it->nosolve = 0;
+ EGLPNUM_TYPENAME_EGlpNumCopy (it->prevobj, lp->pobjval);
+ EGLPNUM_TYPENAME_ILLfct_compute_piz (lp);
+ if (pinf->p_strategy == COMPLETE_PRICING)
+ {
+ EGLPNUM_TYPENAME_ILLfct_compute_dz (lp);
+#if USEHEAP > 0
+ EGLPNUM_TYPENAME_ILLprice_free_heap (pinf);
+#endif
+ EGLPNUM_TYPENAME_ILLprice_compute_dual_inf (lp, pinf, NULL, 0, PRIMAL_PHASEII);
+#if USEHEAP > 0
+ rval = EGLPNUM_TYPENAME_ILLprice_test_for_heap (lp, pinf, lp->nnbasic, pinf->d_scaleinf,
+ PRIMAL_SIMPLEX, 0);
+ CHECKRVALG (rval, CLEANUP);
+#endif
+ }
+ else if (pinf->p_strategy == MULTI_PART_PRICING)
+ {
+ EGLPNUM_TYPENAME_ILLprice_init_mpartial_price (lp, pinf, cphase, COL_PRICING);
+ }
+ }
+
+ monitor_iter (lp, pinf, it, cphase);
+ if (it->nextstep == SIMPLEX_TERMINATE || it->nextstep == SIMPLEX_RESUME ||
+ it->newphase != 0)
+ ILL_CLEANUP;
+
+ EGLPNUM_TYPENAME_ILLprice_primal (lp, pinf, &pr, cphase);
+
+ if (pr.price_stat == PRICE_OPTIMAL)
+ {
+ //ILL_IFTRACE("%s:PRICE_OPTIMAL\n",__func__);
+ if (lp->nbchange != 0)
+ {
+ if (it->sdisplay > 1)
+ {
+ QSlog("unrolling %d bound shifts", lp->nbchange);
+ }
+ EGLPNUM_TYPENAME_ILLfct_unroll_bound_change (lp);
+ EGLPNUM_TYPENAME_ILLfct_check_pfeasible (lp, &fi, lp->tol->pfeas_tol);
+ EGLPNUM_TYPENAME_ILLfct_set_status_values (lp, fi.pstatus, -1, PHASEII, -1);
+
+ /*HHH*/ EGLPNUM_TYPENAME_ILLfct_check_dfeasible (lp, &fi, lp->tol->dfeas_tol);
+ /*HHH* QSlog("primal (opt) infeas %.6f", lp->pinfeas);
+ *HHH* QSlog("dual (opt) infeas %.6f", lp->dinfeas);*/
+
+ if (fi.pstatus != PRIMAL_FEASIBLE)
+ {
+ it->algorithm = DUAL_SIMPLEX;
+ it->nextstep = SIMPLEX_RESUME;
+ it->resumeid = SIMPLEX_RESUME_UNSHIFT;
+ it->pricetype = QS_PRICE_DDEVEX;
+ /* this is to force to exit in the case of bad basis */
+ //QSlog("Resume Unshift %s:%s:%d",__func__,__FILE__,__LINE__);
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->pfeas_tol, SIMPLEX_FACTOR);
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->dfeas_tol, SIMPLEX_FACTOR);
+ it->n_restart++;
+ ILL_CLEANUP;
+ /*
+ * it->nextphase = PRIMAL_PHASEI;
+ * lp->tol->ip_tol /= 5.0;
+ * lp->tol->id_tol /= 5.0;
+ * ILL_CLEANUP;
+ */
+ }
+ }
+
+ if (it->sdisplay > 1)
+ {
+ QSlog("problem seemingly solved");
+ QSlog("seemingly opt = %f",
+ EGLPNUM_TYPENAME_EGlpNumToLf (lp->pobjval));
+ QSlog("retesting soln");
+ }
+ rval = EGLPNUM_TYPENAME_ILLsimplex_retest_psolution (lp, pinf, cphase, &fi);
+ CHECKRVALG (rval, CLEANUP);
+ EGLPNUM_TYPENAME_ILLfct_set_status_values (lp, fi.pstatus, fi.dstatus, PHASEII, PHASEII);
+
+ if (fi.pstatus == PRIMAL_INFEASIBLE)
+ {
+ it->nextphase = PRIMAL_PHASEI;
+ EGLPNUM_TYPENAME_EGlpNumDivUiTo (lp->tol->ip_tol, 5);
+ EGLPNUM_TYPENAME_EGlpNumDivUiTo (lp->tol->id_tol, 5);
+ ILL_IFTRACE ("%s:PINF:%lg\n", __func__, EGLPNUM_TYPENAME_EGlpNumToLf (lp->tol->ip_tol));
+ }
+ else if (fi.dstatus == DUAL_FEASIBLE)
+ {
+ //ILL_IFTRACE("%s:PFEAS_DFEAS\n",__func__);
+ it->solstatus = ILL_LP_SOLVED;
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->objval, lp->pobjval);
+ it->nextstep = SIMPLEX_TERMINATE;
+ }
+ else
+ ILL_IFTRACE ("%s:DINF:%la:%lf\n", __func__, EGLPNUM_TYPENAME_EGlpNumToLf (lp->dinfeas),
+ EGLPNUM_TYPENAME_EGlpNumToLf (lp->dinfeas));
+ ILL_CLEANUP;
+ }
+
+ EGLPNUM_TYPENAME_ILLfct_compute_yz (lp, &(lp->yjz), updz, lp->nbaz[pr.eindex]);
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_YNZ, lp->yjz.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_UPNZ, updz->nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+ ratio_iter = 0;
+ do
+ {
+ EGLPNUM_TYPENAME_ILLratio_pII_test (lp, pr.eindex, pr.dir, &rs);
+ //ILL_IFTRACE("all:%d",rs.lindex);
+ EGLPNUM_TYPENAME_EGlpNumCopy (lbound, rs.lbound);
+ boundch = rs.boundch;
+ ratio_iter++;
+
+ if (boundch)
+ {
+ /*
+ * if (ratio_iter > PARAM_PRATIOTESTS){
+ * lbound = lp->xbz[rs.lindex];
+ * boundch = 0;
+ * }
+ */
+ boundch = 0;
+ bndtype = (rs.lvstat == STAT_UPPER) ? BOUND_UPPER : BOUND_LOWER;
+ rval = EGLPNUM_TYPENAME_ILLfct_bound_shift (lp, lp->baz[rs.lindex], bndtype, lbound);
+ CHECKRVALG (rval, CLEANUP);
+ }
+ } while (boundch);
+
+ if (rs.ratio_stat == RATIO_FAILED)
+ {
+ //ILL_IFTRACE(":%d",rs.lindex);
+ /*
+ * rval = E_SIMPLEX_ERROR;
+ * it->solstatus = ILL_PPHASEII_ERROR;
+ */
+ it->algorithm = DUAL_SIMPLEX;
+ it->nextstep = SIMPLEX_RESUME;
+ it->resumeid = SIMPLEX_RESUME_NUMER;
+ /* this is to force to exit in the case of bad basis */
+ it->n_restart++;
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->pfeas_tol, SIMPLEX_FACTOR);
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->dfeas_tol, SIMPLEX_FACTOR);
+ //QSlog("Resume Numerical %s:%s:%d",__func__,__FILE__,__LINE__);
+ ILL_CLEANUP;
+ }
+ else if (rs.ratio_stat == RATIO_UNBOUNDED)
+ {
+ //ILL_IFTRACE(":%d",rs.lindex);
+ if (lp->nbchange != 0)
+ {
+ if (it->sdisplay > 1)
+ {
+ QSlog("unrolling %d bound shifts", lp->nbchange);
+ }
+ EGLPNUM_TYPENAME_ILLfct_unroll_bound_change (lp);
+ }
+ EGLPNUM_TYPENAME_ILLfct_set_status_values (lp, PRIMAL_UNBOUNDED, -1, PHASEII, -1);
+ it->solstatus = ILL_LP_SOLVED;
+ it->nextstep = SIMPLEX_TERMINATE;
+ ILL_CLEANUP;
+ }
+ else if (rs.ratio_stat == RATIO_NOBCHANGE)
+ {
+ //ILL_IFTRACE(":%d",rs.lindex);
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (lp->pobjval, rs.tz, lp->dz[pr.eindex]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->objval, lp->pobjval);
+ if (!test_progress (lp->pobjval, it->prevobj))
+ it->noprog++;
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (it->prevobj, lp->pobjval);
+ it->noprog = 0;
+ }
+
+ //ILL_IFTRACE("%s:c:%d\n",__func__,rs.lindex);
+ EGLPNUM_TYPENAME_ILLfct_update_xz (lp, rs.tz, pr.eindex, rs.lindex);
+ EGLPNUM_TYPENAME_ILLfct_update_basis_info (lp, pr.eindex, rs.lindex, rs.lvstat);
+ if (pinf->p_strategy == COMPLETE_PRICING)
+ EGLPNUM_TYPENAME_ILLprice_compute_dual_inf (lp, pinf, &pr.eindex, 1, PRIMAL_PHASEII);
+ else if (pinf->p_strategy == MULTI_PART_PRICING)
+ EGLPNUM_TYPENAME_ILLprice_update_mpartial_price (lp, pinf, cphase, COL_PRICING);
+ }
+ else if (rs.ratio_stat == RATIO_BCHANGE)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (alpha, lp->dz[pr.eindex], rs.pivotval);
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (lp->pobjval, rs.tz, lp->dz[pr.eindex]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->objval, lp->pobjval);
+
+ if (!test_progress (lp->pobjval, it->prevobj))
+ {
+ //ILL_IFTRACE(":%d",rs.lindex);
+ if (lp->vtype[lp->nbaz[pr.eindex]] == VFREE ||
+ lp->vtype[lp->baz[rs.lindex]] == VARTIFICIAL)
+ {
+ if (it->noprog > 0)
+ it->noprog--;
+ }
+ else
+ it->noprog++;
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (it->prevobj, lp->pobjval);
+ it->noprog = 0;
+ }
+
+ //ILL_IFTRACE(":%d",rs.lindex);
+ EGLPNUM_TYPENAME_ILLfct_compute_zz (lp, &(lp->zz), rs.lindex);
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_ZNZ, lp->zz.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+ if (pinf->p_strategy == COMPLETE_PRICING)
+ {
+ //ILL_IFTRACE("%s:b\n",__func__);
+ EGLPNUM_TYPENAME_ILLfct_compute_zA (lp, &(lp->zz), &(lp->zA));
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_ZANZ, lp->zA.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+ if (pinf->pII_price == QS_PRICE_PSTEEP)
+ EGLPNUM_TYPENAME_ILLfct_compute_psteep_upv (lp, wz);
+ }
+ rval =
+ EGLPNUM_TYPENAME_ILLprice_update_pricing_info (lp, pinf, cphase, wz, pr.eindex, rs.lindex,
+ rs.pivotval);
+ CHECKRVALG (rval, CLEANUP);
+
+ //ILL_IFTRACE("%s:d:%d\n",__func__,rs.lindex);
+ EGLPNUM_TYPENAME_ILLfct_update_xz (lp, rs.tz, pr.eindex, rs.lindex);
+ EGLPNUM_TYPENAME_ILLfct_update_basis_info (lp, pr.eindex, rs.lindex, rs.lvstat);
+ rval = EGLPNUM_TYPENAME_ILLbasis_update (lp, updz, rs.lindex, &refactor, &singular);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (singular)
+ {
+ it->nextstep = SIMPLEX_RESUME;
+ it->resumeid = SIMPLEX_RESUME_SING;
+ /* this is to force to exit in the case of bad basis */
+ it->n_restart++;
+ //QSlog("Resume Singular %s:%s:%d",__func__,__FILE__,__LINE__);
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->pfeas_tol, SIMPLEX_FACTOR);
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->dfeas_tol, SIMPLEX_FACTOR);
+ ILL_CLEANUP;
+ }
+ if (!refactor)
+ {
+ EGLPNUM_TYPENAME_ILLfct_update_piz (lp, alpha);
+
+ if (pinf->p_strategy == COMPLETE_PRICING)
+ {
+ EGLPNUM_TYPENAME_ILLfct_update_dz (lp, pr.eindex, alpha);
+ EGLPNUM_TYPENAME_ILLprice_compute_dual_inf (lp, pinf, lp->zA.indx, lp->zA.nzcnt,
+ PRIMAL_PHASEII);
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_ZARAVG, lp->zA.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+ }
+ else if (pinf->p_strategy == MULTI_PART_PRICING)
+ {
+ EGLPNUM_TYPENAME_ILLprice_update_mpartial_price (lp, pinf, cphase, COL_PRICING);
+ }
+ }
+ if (refactor != 0 || it->nosolve > PARAM_MAX_NOSOLVE)
+ {
+ EGLPNUM_TYPENAME_ILLfct_compute_xbz (lp);
+ it->newphase = SIMPLEX_PHASE_RECOMP;
+ }
+ }
+
+CLEANUP:
+ EGLPNUM_TYPENAME_EGlpNumClearVar (alpha);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (lbound);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (fi.totinfeas);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (pr.dinfeas);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (pr.pinfeas);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (rs.tz);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (rs.lbound);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (rs.ecoeff);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (rs.pivotval);
+ //EG_RETURN(rval);
+ return rval;
+}
+
+static int dual_phaseI_step (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * pinf,
+ EGLPNUM_TYPENAME_svector * updz,
+ EGLPNUM_TYPENAME_svector * wz,
+ EGLPNUM_TYPENAME_iter_info * it)
+{
+ int rval = 0;
+ int singular = 0;
+ int refactor = 0;
+ int cphase = DUAL_PHASEI;
+ EGLPNUM_TYPE alpha;
+ EGLPNUM_TYPE alpha1;
+ EGLPNUM_TYPENAME_feas_info fi;
+ EGLPNUM_TYPENAME_ratio_res rs;
+ EGLPNUM_TYPENAME_price_res pr;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (alpha);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (alpha1);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (fi.totinfeas);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (pr.dinfeas);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (pr.pinfeas);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (rs.tz);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (rs.lbound);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (rs.ecoeff);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (rs.pivotval);
+ EGLPNUM_TYPENAME_EGlpNumZero (alpha1);
+
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_DPHASE1ITER, 0, EGLPNUM_TYPENAME_zeroLpNum);
+ it->nextstep = SIMPLEX_CONTINUE;
+ it->nextphase = DUAL_PHASEI;
+ lp->final_phase = DUAL_PHASEI;
+ it->nosolve++;
+
+ if (it->newphase != 0)
+ {
+ EGLPNUM_TYPENAME_ILLfct_check_dfeasible (lp, &fi, lp->tol->id_tol);
+ if (it->newphase == SIMPLEX_PHASE_NEW)
+ {
+ it->noprog = 0;
+ if (it->sdisplay)
+ {
+ QSlog("starting dual phase I, nosolve %d", it->nosolve);
+ }
+ }
+ it->newphase = 0;
+ it->nosolve = 0;
+ EGLPNUM_TYPENAME_EGlpNumCopy (it->prevobj, lp->dinfeas);
+
+ EGLPNUM_TYPENAME_ILLfct_compute_phaseI_xbz (lp);
+ if (pinf->d_strategy == COMPLETE_PRICING)
+ {
+#if USEHEAP > 0
+ EGLPNUM_TYPENAME_ILLprice_free_heap (pinf);
+#endif
+ EGLPNUM_TYPENAME_ILLprice_compute_primal_inf (lp, pinf, NULL, 0, DUAL_PHASEI);
+#if USEHEAP > 0
+ rval = EGLPNUM_TYPENAME_ILLprice_test_for_heap (lp, pinf, lp->nrows, pinf->p_scaleinf,
+ DUAL_SIMPLEX, 0);
+ CHECKRVALG (rval, CLEANUP);
+#endif
+ }
+ else if (pinf->d_strategy == MULTI_PART_PRICING)
+ {
+ EGLPNUM_TYPENAME_ILLprice_init_mpartial_price (lp, pinf, cphase, ROW_PRICING);
+ }
+ }
+
+ monitor_iter (lp, pinf, it, cphase);
+ if (it->nextstep == SIMPLEX_TERMINATE || it->nextstep == SIMPLEX_RESUME ||
+ it->newphase != 0)
+ ILL_CLEANUP;
+
+ EGLPNUM_TYPENAME_ILLprice_dual (lp, pinf, cphase, &pr);
+
+ if (pr.price_stat == PRICE_OPTIMAL)
+ {
+ if (it->sdisplay > 1)
+ {
+ QSlog("dual phase I seemingly done");
+ QSlog("retesting soln");
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLsimplex_retest_dsolution (lp, pinf, cphase, &fi);
+ CHECKRVALG (rval, CLEANUP);
+ EGLPNUM_TYPENAME_ILLfct_set_status_values (lp, fi.pstatus, fi.dstatus, PHASEI, PHASEII);
+
+ if (fi.dstatus == DUAL_FEASIBLE)
+ {
+ it->nextphase = DUAL_PHASEII;
+ }
+ else if (fi.pstatus == PRIMAL_FEASIBLE)
+ {
+ it->solstatus = ILL_LP_SOLVED;
+ it->nextstep = SIMPLEX_TERMINATE;
+ }
+ it->newphase = SIMPLEX_PHASE_NEW;
+ ILL_CLEANUP;
+ }
+
+ EGLPNUM_TYPENAME_ILLfct_compute_zz (lp, &(lp->zz), pr.lindex);
+ //ILL_IFTRACE("%s:c\n",__func__);
+ EGLPNUM_TYPENAME_ILLfct_compute_zA (lp, &(lp->zz), &(lp->zA));
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_ZNZ, lp->zz.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_ZANZ, lp->zA.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+
+ EGLPNUM_TYPENAME_ILLratio_dI_test (lp, pr.lindex, pr.lvstat, &rs);
+
+ if (rs.ratio_stat == RATIO_FAILED)
+ {
+ /*
+ * rval = E_SIMPLEX_ERROR;
+ * it->solstatus = ILL_DPHASEI_ERROR;
+ */
+ it->algorithm = PRIMAL_SIMPLEX;
+ it->nextstep = SIMPLEX_RESUME;
+ it->resumeid = SIMPLEX_RESUME_NUMER;
+ /* this is to force to exit in the case of bad basis */
+ it->n_restart++;
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->pfeas_tol, SIMPLEX_FACTOR);
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->dfeas_tol, SIMPLEX_FACTOR);
+ //QSlog("Resume Numerical %s:%s:%d",__func__,__FILE__,__LINE__);
+ ILL_CLEANUP;
+ }
+ else if (rs.ratio_stat == RATIO_BCHANGE)
+ {
+ EGLPNUM_TYPENAME_ILLfct_compute_yz (lp, &(lp->yjz), updz, lp->nbaz[rs.eindex]);
+ rval = EGLPNUM_TYPENAME_ILLfct_test_pivot (lp, pr.lindex, ROW_PIVOT, rs.pivotval);
+ if (rval)
+ {
+ it->n_pivot_fail++;
+ if (it->n_pivot_fail > SIMPLEX_MAX_PIVOT_FAIL)
+ {
+ it->n_pivot_fail = 0;
+ /* this is to force to exit in the case of bad basis */
+ it->n_restart++;
+ it->algorithm = PRIMAL_SIMPLEX;
+ it->nextstep = SIMPLEX_RESUME;
+ it->resumeid = SIMPLEX_RESUME_NUMER;
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->pfeas_tol, SIMPLEX_FACTOR);
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->dfeas_tol, SIMPLEX_FACTOR);
+ //QSlog("Resume Pivot %s:%s:%d",__func__,__FILE__,__LINE__);
+ rval = 0;
+ ILL_CLEANUP;
+ }
+ rval = EGLPNUM_TYPENAME_ILLbasis_factor (lp, &singular);
+ if (singular)
+ MESSAGE (__QS_SB_VERB, "Singular basis found!");
+ CHECKRVALG (rval, CLEANUP);
+ if (singular == 0)
+ refactor = 1;
+ goto END;
+ }
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_YNZ, lp->yjz.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_UPNZ, updz->nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+
+ if (pinf->dI_price == QS_PRICE_DSTEEP)
+ EGLPNUM_TYPENAME_ILLfct_compute_dsteep_upv (lp, wz);
+ rval =
+ EGLPNUM_TYPENAME_ILLprice_update_pricing_info (lp, pinf, cphase, wz, rs.eindex, pr.lindex,
+ rs.pivotval);
+ CHECKRVALG (rval, CLEANUP);
+
+ EGLPNUM_TYPENAME_EGlpNumSubTo (lp->dinfeas, lp->upd.c_obj);
+
+ if (!test_progress (lp->dinfeas, it->prevobj))
+ {
+ if (lp->vtype[lp->baz[pr.lindex]] == VARTIFICIAL ||
+ lp->vtype[lp->nbaz[rs.eindex]] == VFREE)
+ {
+ if (it->noprog > 0)
+ it->noprog--;
+ }
+ else
+ it->noprog++;
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (it->prevobj, lp->dinfeas);
+ it->noprog = 0;
+ }
+
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (alpha, lp->dz[rs.eindex], rs.pivotval);
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (alpha1, lp->xbz[pr.lindex], rs.pivotval);
+
+ EGLPNUM_TYPENAME_ILLfct_update_piz (lp, alpha);
+ EGLPNUM_TYPENAME_ILLfct_update_dz (lp, rs.eindex, alpha);
+ EGLPNUM_TYPENAME_ILLfct_update_dfeas (lp, rs.eindex, &(lp->srhs));
+ EGLPNUM_TYPENAME_ILLfct_compute_dpIy (lp, &(lp->srhs), &(lp->ssoln));
+ EGLPNUM_TYPENAME_ILLfct_update_basis_info (lp, rs.eindex, pr.lindex, pr.lvstat);
+
+#if DENSE_PI > 0
+ EGLPNUM_TYPENAME_fct_test_workvector (lp);
+ EGLPNUM_TYPENAME_fct_test_dfeasible (lp);
+#endif
+ rval = EGLPNUM_TYPENAME_ILLbasis_update (lp, updz, pr.lindex, &refactor, &singular);
+ CHECKRVALG (rval, CLEANUP);
+
+#if DENSE_NORM > 0
+ EGLPNUM_TYPENAME_test_dsteep_norms (lp, pinf);
+#endif
+
+ EGLPNUM_TYPENAME_ILLfct_update_dpI_prices (lp, pinf, &(lp->srhs), &(lp->ssoln), pr.lindex,
+ alpha1);
+
+ END:
+ if (singular)
+ {
+ it->nextstep = SIMPLEX_RESUME;
+ it->resumeid = SIMPLEX_RESUME_SING;
+ /* this is to force to exit in the case of bad basis */
+ it->n_restart++;
+ //QSlog("Resume Singular %s:%s:%d",__func__,__FILE__,__LINE__);
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->pfeas_tol, SIMPLEX_FACTOR);
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->dfeas_tol, SIMPLEX_FACTOR);
+ ILL_CLEANUP;
+ }
+ if (refactor != 0 || it->nosolve > PARAM_MAX_NOSOLVE)
+ {
+ EGLPNUM_TYPENAME_ILLfct_compute_piz (lp);
+ EGLPNUM_TYPENAME_ILLfct_compute_dz (lp);
+ EGLPNUM_TYPENAME_ILLfct_dual_adjust (lp, EGLPNUM_TYPENAME_zeroLpNum);
+ EGLPNUM_TYPENAME_ILLfct_check_dfeasible (lp, &fi, lp->tol->id_tol);
+ EGLPNUM_TYPENAME_ILLfct_set_status_values (lp, -1, fi.dstatus, -1, PHASEII);
+ if (fi.dstatus == DUAL_FEASIBLE)
+ it->nextphase = DUAL_PHASEII;
+
+ it->newphase = SIMPLEX_PHASE_RECOMP;
+ ILL_CLEANUP;
+ }
+ }
+
+#if DENSE_PI > 1
+ EGLPNUM_TYPENAME_fct_test_workvector (lp);
+ EGLPNUM_TYPENAME_fct_test_pI_x (lp, pinf);
+#endif
+
+CLEANUP:
+ EGLPNUM_TYPENAME_EGlpNumClearVar (alpha);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (alpha1);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (fi.totinfeas);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (pr.dinfeas);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (pr.pinfeas);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (rs.tz);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (rs.lbound);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (rs.ecoeff);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (rs.pivotval);
+ //EG_RETURN(rval);
+ return rval;
+}
+
+static int dual_phaseII_step (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * pinf,
+ EGLPNUM_TYPENAME_svector * updz,
+ EGLPNUM_TYPENAME_svector * wz,
+ EGLPNUM_TYPENAME_iter_info * it)
+{
+ int coeffch;
+ int rval = 0;
+ int singular = 0;
+ int refactor = 0;
+ int ratio_iter = 0;
+ int cphase = DUAL_PHASEII;
+ int lcol, ecol;
+ int estat, newphase;
+ EGLPNUM_TYPE x_bi, v_l, eval;
+ EGLPNUM_TYPE ecoeff;
+ EGLPNUM_TYPE alpha;
+ EGLPNUM_TYPE alpha1;
+ EGLPNUM_TYPENAME_feas_info fi;
+ EGLPNUM_TYPENAME_ratio_res rs;
+ EGLPNUM_TYPENAME_price_res pr;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (x_bi);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (v_l);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (eval);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (ecoeff);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (alpha);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (alpha1);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (fi.totinfeas);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (pr.dinfeas);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (pr.pinfeas);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (rs.tz);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (rs.lbound);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (rs.ecoeff);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (rs.pivotval);
+ EGLPNUM_TYPENAME_EGlpNumZero (rs.ecoeff);
+ EGLPNUM_TYPENAME_EGlpNumZero (alpha1);
+
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_DPHASE2ITER, 0, EGLPNUM_TYPENAME_zeroLpNum);
+ it->nextstep = SIMPLEX_CONTINUE;
+ it->nextphase = DUAL_PHASEII;
+ lp->final_phase = DUAL_PHASEII;
+ newphase = it->newphase;
+ it->nosolve++;
+
+ if (it->newphase != 0)
+ {
+ EGLPNUM_TYPENAME_ILLfct_compute_dobj (lp);
+ if (it->newphase == SIMPLEX_PHASE_NEW)
+ {
+ it->noprog = 0;
+ if (it->sdisplay)
+ {
+ QSlog("starting dual phase II, nosolve %d", it->nosolve);
+ }
+ }
+ it->newphase = 0;
+ it->nosolve = 0;
+ EGLPNUM_TYPENAME_EGlpNumCopy (it->prevobj, lp->dobjval);
+ EGLPNUM_TYPENAME_ILLfct_compute_xbz (lp);
+
+ if (pinf->d_strategy == COMPLETE_PRICING)
+ {
+#if USEHEAP > 0
+ EGLPNUM_TYPENAME_ILLprice_free_heap (pinf);
+#endif
+ EGLPNUM_TYPENAME_ILLprice_compute_primal_inf (lp, pinf, NULL, 0, DUAL_PHASEII);
+#if USEHEAP > 0
+ rval = EGLPNUM_TYPENAME_ILLprice_test_for_heap (lp, pinf, lp->nrows, pinf->p_scaleinf,
+ DUAL_SIMPLEX, 0);
+ CHECKRVALG (rval, CLEANUP);
+#endif
+ }
+ else if (pinf->d_strategy == MULTI_PART_PRICING)
+ {
+ EGLPNUM_TYPENAME_ILLprice_init_mpartial_price (lp, pinf, cphase, ROW_PRICING);
+ }
+ }
+
+ monitor_iter (lp, pinf, it, cphase);
+ if (it->nextstep == SIMPLEX_TERMINATE || it->nextstep == SIMPLEX_RESUME ||
+ it->newphase != 0)
+ ILL_CLEANUP;
+
+ EGLPNUM_TYPENAME_ILLprice_dual (lp, pinf, cphase, &pr);
+
+ if (pr.price_stat == PRICE_OPTIMAL)
+ {
+ if (lp->ncchange != 0)
+ {
+ if (it->sdisplay > 1)
+ {
+ QSlog("unrolling %d coef shifts", lp->ncchange);
+ }
+ EGLPNUM_TYPENAME_ILLfct_unroll_coef_change (lp);
+ EGLPNUM_TYPENAME_ILLfct_check_dfeasible (lp, &fi, lp->tol->dfeas_tol);
+ EGLPNUM_TYPENAME_ILLfct_set_status_values (lp, -1, fi.dstatus, -1, PHASEII);
+
+ /*HHH*/ EGLPNUM_TYPENAME_ILLfct_check_pfeasible (lp, &fi, lp->tol->pfeas_tol);
+ /*HHH* QSlog("dual (opt) infeas %.6f", lp->dinfeas);
+ *HHH* QSlog("primal (opt) infeas %.6f", lp->pinfeas);*/
+
+ if (fi.dstatus != DUAL_FEASIBLE)
+ {
+ it->algorithm = PRIMAL_SIMPLEX;
+ it->nextstep = SIMPLEX_RESUME;
+ it->resumeid = SIMPLEX_RESUME_UNSHIFT;
+ it->pricetype = QS_PRICE_PDEVEX;
+ /* this is to force to exit in the case of bad basis */
+ it->n_restart++;
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->pfeas_tol, SIMPLEX_FACTOR);
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->dfeas_tol, SIMPLEX_FACTOR);
+ //QSlog("Resume Unshift %s:%s:%d",__func__,__FILE__,__LINE__);
+ ILL_CLEANUP;
+ /*
+ * it->nextphase = DUAL_PHASEI;
+ * lp->tol->ip_tol /= 5.0;
+ * lp->tol->id_tol /= 5.0;
+ * ILL_CLEANUP;
+ */
+ }
+ }
+ if (it->sdisplay > 1)
+ {
+ //ILL_IFTRACE("\t%s:%s:%d\n",__func__,__FILE__,__LINE__);
+ QSlog("problem seemingly solved");
+ QSlog("seemingly dual opt = %f", EGLPNUM_TYPENAME_EGlpNumToLf (lp->dobjval));
+ QSlog("retesting soln");
+ }
+
+ rval = EGLPNUM_TYPENAME_ILLsimplex_retest_dsolution (lp, pinf, cphase, &fi);
+ CHECKRVALG (rval, CLEANUP);
+ EGLPNUM_TYPENAME_ILLfct_set_status_values (lp, fi.pstatus, fi.dstatus, PHASEII, PHASEII);
+
+ if (fi.dstatus == DUAL_INFEASIBLE)
+ {
+ ILL_IFTRACE ("DUAL_INFEAS: %s\n", __func__);
+ it->nextphase = DUAL_PHASEI;
+ EGLPNUM_TYPENAME_EGlpNumDivUiTo (lp->tol->ip_tol, 5);
+ EGLPNUM_TYPENAME_EGlpNumDivUiTo (lp->tol->id_tol, 5);
+ }
+ else if (fi.pstatus == PRIMAL_FEASIBLE)
+ {
+ ILL_IFTRACE ("PRIM_FEAS: %s\n", __func__);
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->objval, lp->dobjval);
+ it->solstatus = ILL_LP_SOLVED;
+ it->nextstep = SIMPLEX_TERMINATE;
+ }
+ else
+ ILL_IFTRACE ("PRIM_INFEAS: %s\n", __func__);
+ ILL_CLEANUP;
+ }
+
+ EGLPNUM_TYPENAME_ILLfct_compute_zz (lp, &(lp->zz), pr.lindex);
+ //ILL_IFTRACE("%s:d\n",__func__);
+ EGLPNUM_TYPENAME_ILLfct_compute_zA (lp, &(lp->zz), &(lp->zA));
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_ZNZ, lp->zz.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_ZANZ, lp->zA.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+
+ ratio_iter = 0;
+ do
+ {
+ EGLPNUM_TYPENAME_ILLratio_longdII_test (lp, pr.lindex, pr.lvstat, &rs);
+ if (rs.ratio_stat == RATIO_NEGATIVE)
+ {
+ if (it->sdisplay > 1)
+ {
+ QSlog("adjust coefs to remove negative ratio tests");
+ }
+ EGLPNUM_TYPENAME_ILLfct_adjust_viol_coefs (lp);
+ EGLPNUM_TYPENAME_ILLratio_longdII_test (lp, pr.lindex, pr.lvstat, &rs);
+ if (rs.ratio_stat == RATIO_NEGATIVE)
+ {
+ MESSAGE (__QS_SB_VERB, "internal error: bad ratio test");
+ rs.ratio_stat = RATIO_FAILED;
+ break;
+ }
+ }
+
+ coeffch = rs.coeffch;
+ EGLPNUM_TYPENAME_EGlpNumCopy (ecoeff, rs.ecoeff);
+ ratio_iter++;
+
+ if (coeffch)
+ {
+ /*
+ * if (ratio_iter > PARAM_DRATIOTESTS){
+ * ecoeff = lp->cz[lp->nbaz[rs.eindex]] - lp->dz[rs.eindex];
+ * coeffch = 0;
+ * }
+ */
+ coeffch = 0;
+ rval = EGLPNUM_TYPENAME_ILLfct_coef_shift (lp, lp->nbaz[rs.eindex], ecoeff);
+ CHECKRVALG (rval, CLEANUP);
+ }
+ if (rs.ratio_stat == RATIO_BCHANGE)
+ if (lp->vstat[lp->nbaz[rs.eindex]] == STAT_ZERO)
+ break;
+
+ } while (coeffch);
+
+ if (rs.ratio_stat == RATIO_FAILED)
+ {
+ /*
+ * rval = E_SIMPLEX_ERROR;
+ * it->solstatus = ILL_DPHASEII_ERROR;
+ */
+ it->algorithm = PRIMAL_SIMPLEX;
+ it->nextstep = SIMPLEX_RESUME;
+ it->resumeid = SIMPLEX_RESUME_NUMER;
+ /* this is to force to exit in the case of bad basis */
+ it->n_restart++;
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->pfeas_tol, SIMPLEX_FACTOR);
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->dfeas_tol, SIMPLEX_FACTOR);
+ //QSlog("Resume Numerical %s:%s:%d",__func__,__FILE__,__LINE__);
+ ILL_CLEANUP;
+ }
+ else if (rs.ratio_stat == RATIO_UNBOUNDED)
+ {
+ lp->infub_ix = pr.lindex;
+ if (lp->ncchange != 0)
+ {
+ if (it->sdisplay > 1)
+ {
+ QSlog("unrolling %d coef shifts", lp->ncchange);
+ }
+ EGLPNUM_TYPENAME_ILLfct_unroll_coef_change (lp);
+ }
+ EGLPNUM_TYPENAME_ILLfct_set_status_values (lp, -1, DUAL_UNBOUNDED, -1, PHASEII);
+ it->solstatus = ILL_LP_SOLVED;
+ it->nextstep = SIMPLEX_TERMINATE;
+ }
+ else if (rs.ratio_stat == RATIO_BCHANGE)
+ {
+ lcol = lp->baz[pr.lindex];
+ ecol = lp->nbaz[rs.eindex];
+
+ EGLPNUM_TYPENAME_ILLfct_compute_yz (lp, &(lp->yjz), updz, ecol);
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_YNZ, lp->yjz.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_UPNZ, updz->nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+ rval = EGLPNUM_TYPENAME_ILLfct_test_pivot (lp, pr.lindex, ROW_PIVOT, rs.pivotval);
+ if (rval != 0)
+ {
+ it->n_pivot_fail++;
+ if (it->n_pivot_fail > SIMPLEX_MAX_PIVOT_FAIL)
+ {
+ it->n_pivot_fail = 0;
+ /* this is to force to exit in the case of bad basis */
+ it->algorithm = PRIMAL_SIMPLEX;
+ it->nextstep = SIMPLEX_RESUME;
+ it->resumeid = SIMPLEX_RESUME_NUMER;
+ it->n_restart++;
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->pfeas_tol, SIMPLEX_FACTOR);
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->dfeas_tol, SIMPLEX_FACTOR);
+ //QSlog("Resume Pivot %s:%s:%d",__func__,__FILE__,__LINE__);
+ rval = 0;
+ ILL_CLEANUP;
+ }
+ if (newphase == 0)
+ {
+ rval = EGLPNUM_TYPENAME_ILLbasis_factor (lp, &singular);
+ CHECKRVALG (rval, CLEANUP);
+ if (singular)
+ MESSAGE (__QS_SB_VERB, "Singular basis found!");
+#ifdef dbl_QSOPT_CURRENT_PRECICION
+ if (singular)
+ {
+ MESSAGE (__QS_SB_VERB, "Forcing fail!");
+ rval = QS_LP_CHANGE_PREC;
+ }
+#endif
+ if (singular == 0)
+ refactor = 1;
+ goto END;
+ }
+ else
+ {
+ if (it->sdisplay > 1)
+ {
+ QSlog("warning: bad step");
+ }
+ }
+ }
+
+ EGLPNUM_TYPENAME_EGlpNumAddTo (lp->dobjval, lp->upd.c_obj);
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->objval, lp->dobjval);
+
+ if (!test_progress (lp->dobjval, it->prevobj))
+ {
+ if (lp->vtype[lcol] == VARTIFICIAL || lp->vtype[ecol] == VFREE)
+ {
+ if (it->noprog > 0)
+ it->noprog--;
+ }
+ else
+ it->noprog++;
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (it->prevobj, lp->dobjval);
+ it->noprog = 0;
+ }
+
+ if (pinf->dII_price == QS_PRICE_DSTEEP)
+ EGLPNUM_TYPENAME_ILLfct_compute_dsteep_upv (lp, wz);
+ rval =
+ EGLPNUM_TYPENAME_ILLprice_update_pricing_info (lp, pinf, cphase, wz, rs.eindex, pr.lindex,
+ rs.pivotval);
+ CHECKRVALG (rval, CLEANUP);
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (x_bi, lp->xbz[pr.lindex]);
+ if (pr.lvstat == STAT_LOWER)
+ EGLPNUM_TYPENAME_EGlpNumCopy (v_l, lp->lz[lcol]);
+ else
+ EGLPNUM_TYPENAME_EGlpNumCopy (v_l, lp->uz[lcol]);
+ EGLPNUM_TYPENAME_EGlpNumCopy (alpha, rs.tz);
+ if (pr.lvstat == STAT_LOWER)
+ EGLPNUM_TYPENAME_EGlpNumSign (alpha);
+ estat = lp->vstat[ecol];
+ if (estat == STAT_LOWER)
+ EGLPNUM_TYPENAME_EGlpNumCopy (eval, lp->lz[ecol]);
+ else if (estat == STAT_ZERO)
+ EGLPNUM_TYPENAME_EGlpNumZero (eval);
+ else
+ EGLPNUM_TYPENAME_EGlpNumCopy (eval, lp->uz[ecol]);
+
+ EGLPNUM_TYPENAME_ILLfct_update_piz (lp, alpha);
+ EGLPNUM_TYPENAME_ILLfct_update_dz (lp, rs.eindex, alpha);
+ EGLPNUM_TYPENAME_ILLfct_update_dIIfeas (lp, rs.eindex, &(lp->srhs));
+ EGLPNUM_TYPENAME_ILLfct_compute_dpIIy (lp, &(lp->srhs), &(lp->ssoln));
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (alpha1, x_bi, v_l);
+ EGLPNUM_TYPENAME_EGlpNumSubTo (alpha1, lp->upd.dty);
+ EGLPNUM_TYPENAME_EGlpNumDivTo (alpha1, rs.pivotval);
+ EGLPNUM_TYPENAME_ILLfct_update_basis_info (lp, rs.eindex, pr.lindex, pr.lvstat);
+ rval = EGLPNUM_TYPENAME_ILLbasis_update (lp, updz, pr.lindex, &refactor, &singular);
+ CHECKRVALG (rval, CLEANUP);
+
+ EGLPNUM_TYPENAME_ILLfct_update_dpII_prices (lp, pinf, &(lp->srhs), &(lp->ssoln), /*rs.eindex,*/
+ pr.lindex, eval, alpha1);
+
+#if DENSE_NORM > 0
+ EGLPNUM_TYPENAME_test_dsteep_norms (lp, pinf);
+#endif
+
+ END:
+ if (singular)
+ {
+ it->nextstep = SIMPLEX_RESUME;
+ it->resumeid = SIMPLEX_RESUME_SING;
+ /* this is to force to exit in the case of bad basis */
+ it->n_restart++;
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->pfeas_tol, SIMPLEX_FACTOR);
+ EGLPNUM_TYPENAME_EGlpNumMultUiTo (lp->tol->dfeas_tol, SIMPLEX_FACTOR);
+ //QSlog("Resume Singular %s:%s:%d",__func__,__FILE__,__LINE__);
+ ILL_CLEANUP;
+ }
+ if (refactor != 0 || it->nosolve > PARAM_MAX_NOSOLVE)
+ {
+ EGLPNUM_TYPENAME_ILLfct_compute_piz (lp);
+ EGLPNUM_TYPENAME_ILLfct_compute_dz (lp);
+ EGLPNUM_TYPENAME_ILLfct_dual_adjust (lp, EGLPNUM_TYPENAME_zeroLpNum);
+ it->newphase = SIMPLEX_PHASE_RECOMP;
+ }
+ }
+
+#if DENSE_PIIPI > 0
+ EGLPNUM_TYPENAME_fct_test_workvector (lp);
+ if (!refactor)
+ {
+ EGLPNUM_TYPENAME_fct_test_pII_x (lp, pinf);
+ EGLPNUM_TYPENAME_fct_test_pII_pi_dz (lp, pinf);
+ }
+#endif
+
+CLEANUP:
+ EGLPNUM_TYPENAME_EGlpNumClearVar (x_bi);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (v_l);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (eval);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ecoeff);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (alpha);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (alpha1);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (fi.totinfeas);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (pr.dinfeas);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (pr.pinfeas);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (rs.tz);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (rs.lbound);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (rs.ecoeff);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (rs.pivotval);
+ //EG_RETURN(rval);
+ return rval;
+}
+
+static void get_current_stat (
+ EGLPNUM_TYPENAME_lp_status_info * p,
+ int algorithm,
+ int *bstat)
+{
+ if (p->optimal)
+ *bstat = OPTIMAL;
+ else if (algorithm == PRIMAL_SIMPLEX)
+ {
+ if (p->primal_feasible)
+ *bstat = PRIMAL_FEASIBLE;
+ else if (p->primal_infeasible)
+ *bstat = PRIMAL_INFEASIBLE;
+ else if (p->primal_unbounded)
+ *bstat = PRIMAL_UNBOUNDED;
+ else
+ *bstat = NONOPTIMAL;
+ }
+ else if (algorithm == DUAL_SIMPLEX)
+ {
+ if (p->dual_feasible)
+ *bstat = DUAL_FEASIBLE;
+ else if (p->dual_infeasible)
+ *bstat = DUAL_INFEASIBLE;
+ else if (p->dual_unbounded)
+ *bstat = DUAL_UNBOUNDED;
+ else
+ *bstat = NONOPTIMAL;
+ }
+}
+
+int EGLPNUM_TYPENAME_ILLsimplex_pivotin (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_price_info * pinf,
+ int rcnt,
+ int *rlist,
+ int pivot_opt,
+ int *basis_mod)
+{
+ int i, npiv = 0;
+ int eindex;
+ int rval = 0;
+ int singular = 0;
+ int refactor = 0;
+ int *rowmap = lp->O->rowmap;
+ int *clist = NULL;
+ EGLPNUM_TYPENAME_svector wz;
+ EGLPNUM_TYPENAME_svector updz;
+ EGLPNUM_TYPE alpha;
+ EGLPNUM_TYPENAME_ratio_res rs;
+ EGLPNUM_TYPENAME_feas_info fi;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (alpha);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (fi.totinfeas);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (rs.tz);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (rs.lbound);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (rs.ecoeff);
+ EGLPNUM_TYPENAME_EGlpNumInitVar (rs.pivotval);
+ EGLPNUM_TYPENAME_EGlpNumZero (alpha);
+
+ *basis_mod = 0;
+ if (rcnt <= 0)
+ {
+ EG_RETURN (rval);
+ }
+
+ if (pivot_opt == SIMPLEX_PIVOTINROW)
+ {
+ ILL_SAFE_MALLOC (clist, rcnt, int);
+
+ for (i = 0; i < rcnt; i++)
+ clist[i] = rowmap[rlist[i]];
+ }
+ else
+ clist = rlist;
+
+ for (i = 0; i < rcnt; i++)
+ {
+ if (lp->vstat[clist[i]] != STAT_BASIC)
+ {
+ *basis_mod = 1;
+ break;
+ }
+ }
+ if (*basis_mod == 0)
+ {
+ if (pivot_opt == SIMPLEX_PIVOTINROW)
+ {
+ ILL_IFFREE (clist, int);
+ }
+ EG_RETURN (rval);
+ }
+
+ /* QSlog("Forcing vars into basis in EGLPNUM_TYPENAME_ILLsimplex_pivotin"); */
+ EGLPNUM_TYPENAME_ILLsvector_init (&wz);
+ rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&wz, lp->nrows);
+ CHECKRVALG (rval, CLEANUP);
+ EGLPNUM_TYPENAME_ILLsvector_init (&updz);
+ rval = EGLPNUM_TYPENAME_ILLsvector_alloc (&updz, lp->nrows);
+ CHECKRVALG (rval, CLEANUP);
+
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->pobjval, lp->dobjval);
+ for (i = 0; i < rcnt; i++)
+ {
+ if (lp->vstat[clist[i]] == STAT_BASIC)
+ continue;
+ npiv++;
+
+ eindex = lp->vindex[clist[i]];
+ EGLPNUM_TYPENAME_ILLfct_compute_yz (lp, &(lp->yjz), &updz, lp->nbaz[eindex]);
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_YNZ, lp->yjz.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_UPNZ, updz.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+
+ EGLPNUM_TYPENAME_ILLratio_pivotin_test (lp, clist, rcnt, &rs);
+
+ if (rs.ratio_stat == RATIO_UNBOUNDED || rs.ratio_stat == RATIO_FAILED)
+ {
+ QSlog("Pivot_in failed");
+ rval = E_SIMPLEX_ERROR;
+ ILL_CLEANUP;
+ }
+ else if (rs.ratio_stat == RATIO_BCHANGE)
+ {
+ if (rs.lvstat == STAT_LOWER)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (alpha, lp->lz[lp->baz[rs.lindex]], lp->xbz[rs.lindex]);
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (lp->dobjval, rs.tz, alpha);
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopyDiff (alpha, lp->xbz[rs.lindex], lp->uz[lp->baz[rs.lindex]]);
+ EGLPNUM_TYPENAME_EGlpNumAddInnProdTo (lp->dobjval, rs.tz, alpha);
+ }
+ EGLPNUM_TYPENAME_EGlpNumCopyFrac (alpha, lp->dz[eindex], rs.pivotval);
+ EGLPNUM_TYPENAME_EGlpNumCopy (lp->objval, lp->dobjval);
+
+ EGLPNUM_TYPENAME_ILLfct_compute_zz (lp, &(lp->zz), rs.lindex);
+ //ILL_IFTRACE("%s:e\n",__func__);
+ EGLPNUM_TYPENAME_ILLfct_compute_zA (lp, &(lp->zz), &(lp->zA));
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_ZNZ, lp->zz.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+ EGLPNUM_TYPENAME_ILLfct_update_counts (lp, CNT_ZANZ, lp->zA.nzcnt, EGLPNUM_TYPENAME_zeroLpNum);
+
+ if (pinf->dsinfo.norms && pinf->dII_price == QS_PRICE_DSTEEP)
+ {
+ EGLPNUM_TYPENAME_ILLfct_compute_dsteep_upv (lp, &wz);
+ rval = EGLPNUM_TYPENAME_ILLprice_update_pricing_info (lp, pinf, DUAL_PHASEII, &wz,
+ eindex, rs.lindex, rs.pivotval);
+ CHECKRVALG (rval, CLEANUP);
+ }
+ else if (pinf->psinfo.norms && pinf->pII_price == QS_PRICE_PSTEEP)
+ {
+ EGLPNUM_TYPENAME_ILLfct_compute_psteep_upv (lp, &wz);
+ rval = EGLPNUM_TYPENAME_ILLprice_update_pricing_info (lp, pinf, PRIMAL_PHASEII, &wz,
+ eindex, rs.lindex, rs.pivotval);
+ CHECKRVALG (rval, CLEANUP);
+ }
+
+ //ILL_IFTRACE("%s:e\n",__func__);
+ EGLPNUM_TYPENAME_ILLfct_update_xz (lp, rs.tz, eindex, rs.lindex);
+ EGLPNUM_TYPENAME_ILLfct_update_basis_info (lp, eindex, rs.lindex, rs.lvstat);
+ rval = EGLPNUM_TYPENAME_ILLbasis_update (lp, &updz, rs.lindex, &refactor, &singular);
+ CHECKRVALG (rval, CLEANUP);
+
+ if (singular)
+ {
+ QSlog("singular matrix in pivot_in");
+ rval = E_SIMPLEX_ERROR;
+ ILL_CLEANUP;
+ }
+ if (!refactor)
+ {
+ EGLPNUM_TYPENAME_ILLfct_update_piz (lp, alpha);
+ EGLPNUM_TYPENAME_ILLfct_update_dz (lp, eindex, alpha);
+ }
+ else
+ {
+ EGLPNUM_TYPENAME_ILLfct_compute_xbz (lp);
+ EGLPNUM_TYPENAME_ILLfct_compute_piz (lp);
+ EGLPNUM_TYPENAME_ILLfct_compute_dz (lp);
+ EGLPNUM_TYPENAME_ILLfct_compute_dobj (lp);
+ }
+ }
+ }
+ /*
+ * EGLPNUM_TYPENAME_ILLfct_dphaseI_simple_update (lp, lp->tol->dfeas_tol);
+ * EGLPNUM_TYPENAME_ILLfct_compute_xbz (lp);
+ * EGLPNUM_TYPENAME_ILLfct_compute_dobj (lp);
+ */
+
+ EGLPNUM_TYPENAME_ILLfct_check_pfeasible (lp, &fi, lp->tol->pfeas_tol);
+ EGLPNUM_TYPENAME_ILLfct_check_dfeasible (lp, &fi, lp->tol->dfeas_tol);
+ EGLPNUM_TYPENAME_ILLfct_set_status_values (lp, fi.pstatus, fi.dstatus, PHASEII, PHASEII);
+
+CLEANUP:
+ if (pivot_opt == SIMPLEX_PIVOTINROW)
+ ILL_IFFREE (clist, int);
+
+ EGLPNUM_TYPENAME_ILLsvector_free (&wz);
+ EGLPNUM_TYPENAME_ILLsvector_free (&updz);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (alpha);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (fi.totinfeas);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (rs.tz);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (rs.lbound);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (rs.ecoeff);
+ EGLPNUM_TYPENAME_EGlpNumClearVar (rs.pivotval);
+ EG_RETURN (rval);
+}
+
+static int report_value (
+ EGLPNUM_TYPENAME_lpinfo * lp,
+ EGLPNUM_TYPENAME_iter_info * it,
+ const char *value_name,
+ EGLPNUM_TYPE value)
+{
+ int rval = 0;
+
+ if (it->sdisplay && it->itercnt % lp->iterskip == 0)
+ {
+ char buffer[1024];
+
+ snprintf (buffer, (size_t) 1023, "(%d): %s = %10.7lf", it->itercnt,
+ value_name, EGLPNUM_TYPENAME_EGlpNumToLf (value));
+ rval = ILLstring_report (buffer, &lp->O->reporter);
+ }
+ else
+ {
+ /* make sure ILLstring_report is called at least every 10 iterations */
+ if (it->itercnt % (lp->iterskip / 10))
+ {
+ rval = ILLstring_report (NULL, &lp->O->reporter);
+ }
+ }
+ if (rval != 0)
+ { /* ILLstring_report was called and failed, which means we should abort */
+ it->solstatus = QS_LP_ABORTED;
+ }
+ return rval;
+}
+
+#undef QSOPT_CURRENT_PRECICION
diff --git a/qsopt_ex/simplex.h b/qsopt_ex/simplex.h
new file mode 100644
index 0000000..2a42bf7
--- /dev/null
+++ b/qsopt_ex/simplex.h
@@ -0,0 +1,89 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* $RCSfile: simplex_EGLPNUM_TYPENAME.h,v $ $Revision: 1.3 $ $Date: 2003/11/05 16:57:39 $ */
+
+#ifndef EGLPNUM_TYPENAME___SIMPLEX_H
+#define EGLPNUM_TYPENAME___SIMPLEX_H
+
+struct itcnt_t;
+
+#include "lpdata_EGLPNUM_TYPENAME.h"
+#include "basicdefs.h"
+
+typedef struct EGLPNUM_TYPENAME_param_info
+{
+ int origalgo;
+ int pphaseI;
+ int pphaseII;
+ int dphaseI;
+ int dphaseII;
+ int p_strategy;
+ int d_strategy;
+}
+EGLPNUM_TYPENAME_param_info;
+
+typedef struct EGLPNUM_TYPENAME_iter_info
+{
+ int newphase;
+ int nextphase;
+ int nextstep;
+ int sdisplay;
+ int itercnt;
+ int solstatus;
+ int curtime;
+ int rounds;
+ int chkobj;
+ int nosolve;
+ int noprog;
+ int inner;
+ int algorithm;
+ int resumeid;
+ int pricetype;
+ int n_restart;
+ int n_pivot_fail;
+ EGLPNUM_TYPE prevobj;
+ EGLPNUM_TYPE objtol;
+ EGLPNUM_TYPENAME_param_info oldinfo;
+}
+EGLPNUM_TYPENAME_iter_info;
+
+void EGLPNUM_TYPENAME_ILLsimplex_init_lpinfo ( EGLPNUM_TYPENAME_lpinfo * lp),
+ EGLPNUM_TYPENAME_ILLsimplex_free_lpinfo ( EGLPNUM_TYPENAME_lpinfo * lp),
+ EGLPNUM_TYPENAME_ILLsimplex_load_lpinfo ( EGLPNUM_TYPENAME_ILLlpdata * qslp, EGLPNUM_TYPENAME_lpinfo * lp),
+ EGLPNUM_TYPENAME_ILLsimplex_set_bound ( EGLPNUM_TYPENAME_lpinfo * lp, const EGLPNUM_TYPE * objbound, int sense);
+void EGLPNUM_TYPENAME_free_internal_lpinfo ( EGLPNUM_TYPENAME_lpinfo * lp);
+void EGLPNUM_TYPENAME_init_internal_lpinfo ( EGLPNUM_TYPENAME_lpinfo * lp);
+int EGLPNUM_TYPENAME_build_internal_lpinfo ( EGLPNUM_TYPENAME_lpinfo * lp);
+int EGLPNUM_TYPENAME_ILLsimplex_retest_psolution ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_price_info * p, int phase,
+ EGLPNUM_TYPENAME_feas_info * fs),
+ EGLPNUM_TYPENAME_ILLsimplex_retest_dsolution ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_price_info * p, int phase,
+ EGLPNUM_TYPENAME_feas_info * fs),
+ EGLPNUM_TYPENAME_ILLsimplex_solution ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPE * xz, EGLPNUM_TYPE * piz,
+ EGLPNUM_TYPE * dz, EGLPNUM_TYPE * objval),
+ EGLPNUM_TYPENAME_ILLsimplex_infcertificate ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPE * pi),
+ EGLPNUM_TYPENAME_ILLsimplex ( EGLPNUM_TYPENAME_lpinfo * lp, int algorithm, EGLPNUM_TYPENAME_ILLlp_basis * B,
+ EGLPNUM_TYPENAME_price_info * pinf, int *sol_status, int sdisplay, itcnt_t* itcnt),
+ EGLPNUM_TYPENAME_ILLsimplex_pivotin ( EGLPNUM_TYPENAME_lpinfo * lp, EGLPNUM_TYPENAME_price_info * pinf, int rcnt,
+ int *rlist, int pivot_opt, int *basis_mod);
+
+#endif /* EGLPNUM_TYPENAME___SIMPLEX_H */
diff --git a/qsopt_ex/sortrus.c b/qsopt_ex/sortrus.c
new file mode 100644
index 0000000..b68e397
--- /dev/null
+++ b/qsopt_ex/sortrus.c
@@ -0,0 +1,289 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCSINFO $Id: sortrus.c,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+/****************************************************************************/
+/* */
+/* This file is part of CONCORDE */
+/* */
+/* (c) Copyright 1995--1999 by David Applegate, Robert Bixby, */
+/* Vasek Chvatal, and William Cook */
+/* */
+/* Permission is granted for academic research use. For other uses, */
+/* contact the authors for licensing options. */
+/* */
+/* Use at your own risk. We make no guarantees about the */
+/* correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* SORTING ROUTINES */
+/* */
+/* TSP CODE */
+/* */
+/* Written by: Applegate, Bixby, Chvatal, and Cook */
+/* DATE: February 24, 1994 */
+/* */
+/* EXPORTED FUNCTIONS: */
+/* */
+/* char *ILLutil_linked_radixsort (char *data, char *datanext, */
+/* char *dataval, int valsize) */
+/* USAGE: */
+/* head = (bar *) ILLutil_linked_radixsort ((char *) head, */
+/* (char *) &(head->next), (char *) &(head->val), sizeof (int)); */
+/* Then head is the start of the linked list in increasing order of */
+/* val, with next as the field that links the bars. */
+/* WARNING: DOES NOT HANDLE NEGATIVE NUMBERS PROPERLY. */
+/* */
+/* void ILLutil_int_array_quicksort (int *len, int n) */
+/* len - the array to be sorted */
+/* n - the number of elements in len */
+/* Uses quicksort to put len in increasing order. */
+/* */
+/* void ILLutil_int_perm_quicksort (int *perm, int *len, int n) */
+/* perm - must be allocated and initialized by the calling routine, */
+/* it will be arranged in increasing order of len. */
+/* n - the number of elements in perm and len. */
+/* */
+/* void ILLutil_double_perm_quicksort (int *perm, double *len, int n) */
+/* perm - must be allocated and initialized by the calling routine, */
+/* it will be arranged in increasing order of len. */
+/* n - the number of elements in perm and len. */
+/* */
+/* void ILLutil_rselect (int *arr, int l, int r, int m, */
+/* double *coord, ILLrandstate *rstate) */
+/* arr - permutation that will be rearranged */
+/* l,r - specify the range of arr that we are interested in */
+/* m - is the index into l,r that is the break point for the perm */
+/* coord - gives the keys that determine the ordering */
+/* */
+/****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "eg_lpnum.h"
+
+#include "util.h"
+#include "except.h"
+
+
+#define BITS_PER_PASS (8)
+
+#define NBINS (1<<BITS_PER_PASS)
+
+
+static void select_EGlpNum_split (
+ int *arr,
+ int n,
+ EGLPNUM_TYPE * v,
+ int *start,
+ int *end,
+ EGLPNUM_TYPE * coord),
+ select_EGlpNum_sort (
+ int *arr,
+ int n,
+ EGLPNUM_TYPE * coord),
+ select_EGlpNum_sort_dsample (
+ EGLPNUM_TYPE * samp,
+ int n);
+
+void EGLPNUM_TYPENAME_ILLutil_EGlpNum_perm_quicksort (
+ int *perm,
+ EGLPNUM_TYPE * len,
+ int n)
+{
+ int i, j, temp;
+ EGLPNUM_TYPE t;
+
+ if (n <= 1)
+ return;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (t);
+ ILL_SWAP (perm[0], perm[(n - 1) / 2], temp);
+
+ i = 0;
+ j = n;
+ EGLPNUM_TYPENAME_EGlpNumCopy (t, len[perm[0]]);
+
+ for (;;)
+ {
+ do
+ i++;
+ while (i < n && EGLPNUM_TYPENAME_EGlpNumIsLess (len[perm[i]], t));
+ do
+ j--;
+ while (EGLPNUM_TYPENAME_EGlpNumIsLess (t, len[perm[j]]));
+ if (j < i)
+ break;
+ ILL_SWAP (perm[i], perm[j], temp);
+ }
+ ILL_SWAP (perm[0], perm[j], temp);
+
+ EGLPNUM_TYPENAME_EGlpNumClearVar (t);
+ EGLPNUM_TYPENAME_ILLutil_EGlpNum_perm_quicksort (perm, len, j);
+ EGLPNUM_TYPENAME_ILLutil_EGlpNum_perm_quicksort (perm + i, len, n - i);
+}
+
+/********** Median - Select Routines **********/
+
+/* NSAMPLES should be odd */
+#define NSAMPLES 3
+#define SORTSIZE 20
+
+
+void EGLPNUM_TYPENAME_ILLutil_EGlpNum_rselect (
+ int *arr,
+ int l,
+ int r,
+ int m,
+ EGLPNUM_TYPE * coord,
+ ILLrandstate * rstate)
+{
+ EGLPNUM_TYPE *samplevals = EGLPNUM_TYPENAME_EGlpNumAllocArray (NSAMPLES);
+ int i;
+ int st, en;
+ int n;
+
+ arr += l;
+ n = r - l + 1;
+ m -= l;
+
+ while (n > SORTSIZE)
+ {
+ for (i = 0; i < NSAMPLES; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (samplevals[i], coord[arr[ILLutil_lprand (rstate) % n]]);
+ }
+ select_EGlpNum_sort_dsample (samplevals, NSAMPLES);
+ select_EGlpNum_split (arr, n, &(samplevals[(NSAMPLES - 1) / 2]),
+ &st, &en, coord);
+ if (st > m)
+ {
+ n = st;
+ }
+ else if (en <= m)
+ {
+ arr += en;
+ n -= en;
+ m -= en;
+ }
+ else
+ {
+ return;
+ }
+ }
+
+ select_EGlpNum_sort (arr, n, coord);
+ EGLPNUM_TYPENAME_EGlpNumFreeArray (samplevals);
+ return;
+}
+
+static void select_EGlpNum_split (
+ int *arr,
+ int n,
+ EGLPNUM_TYPE * v,
+ int *start,
+ int *end,
+ EGLPNUM_TYPE * coord)
+{
+ int i, j, k;
+ int t;
+
+ i = 0;
+ j = k = n;
+
+ while (i < j)
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsLess (coord[arr[i]], *v))
+ {
+ i++;
+ }
+ else if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (coord[arr[i]], *v))
+ {
+ j--;
+ ILL_SWAP (arr[i], arr[j], t);
+ }
+ else
+ {
+ j--;
+ k--;
+ t = arr[i];
+ arr[i] = arr[j];
+ arr[j] = arr[k];
+ arr[k] = t;
+ }
+ }
+ *start = j;
+ *end = k;
+ return;
+}
+
+static void select_EGlpNum_sort (
+ int *arr,
+ int n,
+ EGLPNUM_TYPE * coord)
+{
+ int i, j;
+ int t;
+
+ for (i = 1; i < n; i++)
+ {
+ t = arr[i];
+ for (j = i; j > 0 && EGLPNUM_TYPENAME_EGlpNumIsLess (coord[t], coord[arr[j - 1]]); j--)
+ {
+ arr[j] = arr[j - 1];
+ }
+ arr[j] = t;
+ }
+}
+
+static void select_EGlpNum_sort_dsample (
+ EGLPNUM_TYPE * samp,
+ int n)
+{
+ int i, j;
+ EGLPNUM_TYPE t;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (t);
+
+ for (i = 1; i < n; i++)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (t, samp[i]);
+ for (j = i; j > 0 && EGLPNUM_TYPENAME_EGlpNumIsLess (t, samp[j - 1]); j--)
+ {
+ EGLPNUM_TYPENAME_EGlpNumCopy (samp[j], samp[j - 1]);
+ }
+ EGLPNUM_TYPENAME_EGlpNumCopy (samp[j], t);
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (t);
+}
+
+
+
+
diff --git a/qsopt_ex/sortrus.h b/qsopt_ex/sortrus.h
new file mode 100644
index 0000000..a32b822
--- /dev/null
+++ b/qsopt_ex/sortrus.h
@@ -0,0 +1,44 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+#ifndef EGLPNUM_TYPENAME___SORTRUS_H__
+#define EGLPNUM_TYPENAME___SORTRUS_H__
+/****************************************************************************/
+/* */
+/* sortrus.c */
+/* */
+/****************************************************************************/
+
+#include "urandom.h"
+
+void EGLPNUM_TYPENAME_ILLutil_EGlpNum_perm_quicksort (
+ int *perm,
+ EGLPNUM_TYPE * len,
+ int n),
+ EGLPNUM_TYPENAME_ILLutil_EGlpNum_rselect (
+ int *arr,
+ int l,
+ int r,
+ int m,
+ EGLPNUM_TYPE * coord,
+ ILLrandstate * rstate);
+#endif
diff --git a/qsopt_ex/sortrus_common.c b/qsopt_ex/sortrus_common.c
new file mode 100644
index 0000000..21b3793
--- /dev/null
+++ b/qsopt_ex/sortrus_common.c
@@ -0,0 +1,426 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCSINFO $Id: sortrus.c,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+/****************************************************************************/
+/* */
+/* This file is part of CONCORDE */
+/* */
+/* (c) Copyright 1995--1999 by David Applegate, Robert Bixby, */
+/* Vasek Chvatal, and William Cook */
+/* */
+/* Permission is granted for academic research use. For other uses, */
+/* contact the authors for licensing options. */
+/* */
+/* Use at your own risk. We make no guarantees about the */
+/* correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* SORTING ROUTINES */
+/* */
+/* TSP CODE */
+/* */
+/* Written by: Applegate, Bixby, Chvatal, and Cook */
+/* DATE: February 24, 1994 */
+/* */
+/* EXPORTED FUNCTIONS: */
+/* */
+/* char *ILLutil_linked_radixsort (char *data, char *datanext, */
+/* char *dataval, int valsize) */
+/* USAGE: */
+/* head = (bar *) ILLutil_linked_radixsort ((char *) head, */
+/* (char *) &(head->next), (char *) &(head->val), sizeof (int)); */
+/* Then head is the start of the linked list in increasing order of */
+/* val, with next as the field that links the bars. */
+/* WARNING: DOES NOT HANDLE NEGATIVE NUMBERS PROPERLY. */
+/* */
+/* void ILLutil_int_array_quicksort (int *len, int n) */
+/* len - the array to be sorted */
+/* n - the number of elements in len */
+/* Uses quicksort to put len in increasing order. */
+/* */
+/* void ILLutil_int_perm_quicksort (int *perm, int *len, int n) */
+/* perm - must be allocated and initialized by the calling routine, */
+/* it will be arranged in increasing order of len. */
+/* n - the number of elements in perm and len. */
+/* */
+/* void ILLutil_double_perm_quicksort (int *perm, double *len, int n) */
+/* perm - must be allocated and initialized by the calling routine, */
+/* it will be arranged in increasing order of len. */
+/* n - the number of elements in perm and len. */
+/* */
+/* void ILLutil_rselect (int *arr, int l, int r, int m, */
+/* double *coord, ILLrandstate *rstate) */
+/* arr - permutation that will be rearranged */
+/* l,r - specify the range of arr that we are interested in */
+/* m - is the index into l,r that is the break point for the perm */
+/* coord - gives the keys that determine the ordering */
+/* */
+/****************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "qs_config.h"
+#include "util.h"
+#include "except.h"
+
+
+#define BITS_PER_PASS (8)
+
+#define NBINS (1<<BITS_PER_PASS)
+
+
+static void select_split (
+ int *arr,
+ int n,
+ double v,
+ int *start,
+ int *end,
+ double *coord),
+ select_sort (
+ int *arr,
+ int n,
+ double *coord),
+ select_sort_dsample (
+ double *samp,
+ int n);
+
+
+
+char *ILLutil_linked_radixsort (
+ char *data,
+ char *datanext,
+ char *dataval,
+ int valsize)
+{
+ size_t nextoff = datanext - data;
+ size_t valoff = dataval - data;
+ int i;
+ char *head[NBINS];
+ char **tail[NBINS];
+ char *p;
+ char **last;
+ int j;
+ int v;
+
+
+ for (j = valsize - 1; j >= 0; j--)
+ {
+ for (i = 0; i < NBINS; i++)
+ {
+ head[i] = (char *) NULL;
+ tail[i] = &head[i];
+ }
+ for (p = data; p; p = *(char **) (p + nextoff))
+ {
+ v = (unsigned char) p[valoff + j];
+ *tail[v] = p;
+ tail[v] = (char **) (p + nextoff);
+ }
+ last = &data;
+ for (i = 0; i < NBINS; i++)
+ {
+ if (head[i])
+ {
+ *last = head[i];
+ last = tail[i];
+ }
+ }
+ *last = (char *) NULL;
+ }
+ return data;
+}
+
+void ILLutil_int_array_quicksort (
+ int *len,
+ int n)
+{
+ int i, j, temp, t;
+
+ if (n <= 1)
+ return;
+
+ ILL_SWAP (len[0], len[(n - 1) / 2], temp);
+
+ i = 0;
+ j = n;
+ t = len[0];
+
+ for (;;)
+ {
+ do
+ i++;
+ while (i < n && len[i] < t);
+ do
+ j--;
+ while (len[j] > t);
+ if (j < i)
+ break;
+ ILL_SWAP (len[i], len[j], temp);
+ }
+ ILL_SWAP (len[0], len[j], temp);
+
+ ILLutil_int_array_quicksort (len, j);
+ ILLutil_int_array_quicksort (len + i, n - i);
+}
+
+void ILLutil_int_perm_quicksort (
+ int *perm,
+ int *len,
+ int n)
+{
+ int i, j, temp, t;
+
+ if (n <= 1)
+ return;
+
+ ILL_SWAP (perm[0], perm[(n - 1) / 2], temp);
+
+ i = 0;
+ j = n;
+ t = len[perm[0]];
+
+ for (;;)
+ {
+ do
+ i++;
+ while (i < n && len[perm[i]] < t);
+ do
+ j--;
+ while (len[perm[j]] > t);
+ if (j < i)
+ break;
+ ILL_SWAP (perm[i], perm[j], temp);
+ }
+ ILL_SWAP (perm[0], perm[j], temp);
+
+ ILLutil_int_perm_quicksort (perm, len, j);
+ ILLutil_int_perm_quicksort (perm + i, len, n - i);
+}
+
+
+void ILLutil_double_perm_quicksort (
+ int *perm,
+ double *len,
+ int n)
+{
+ int i, j, temp;
+ double t;
+
+ if (n <= 1)
+ return;
+
+ ILL_SWAP (perm[0], perm[(n - 1) / 2], temp);
+
+ i = 0;
+ j = n;
+ t = len[perm[0]];
+
+ for (;;)
+ {
+ do
+ i++;
+ while (i < n && len[perm[i]] < t);
+ do
+ j--;
+ while (t < len[perm[j]]);
+ if (j < i)
+ break;
+ ILL_SWAP (perm[i], perm[j], temp);
+ }
+ ILL_SWAP (perm[0], perm[j], temp);
+
+ ILLutil_double_perm_quicksort (perm, len, j);
+ ILLutil_double_perm_quicksort (perm + i, len, n - i);
+}
+
+void ILLutil_str_perm_quicksort (
+ int *perm,
+ char **len,
+ int n)
+{
+ int i, j, temp;
+ char *t;
+
+ if (n <= 1)
+ return;
+
+ ILL_SWAP (perm[0], perm[(n - 1) / 2], temp);
+
+ i = 0;
+ j = n;
+ t = len[perm[0]];
+
+ for (;;)
+ {
+ do
+ i++;
+ while (i < n && (strcmp (len[perm[i]], t) < 0));
+ do
+ j--;
+ while (strcmp (len[perm[j]], t) > 0);
+ if (j < i)
+ break;
+ ILL_SWAP (perm[i], perm[j], temp);
+ }
+ ILL_SWAP (perm[0], perm[j], temp);
+
+ ILLutil_str_perm_quicksort (perm, len, j);
+ ILLutil_str_perm_quicksort (perm + i, len, n - i);
+}
+
+
+/********** Median - Select Routines **********/
+
+/* NSAMPLES should be odd */
+#define NSAMPLES 3
+#define SORTSIZE 20
+
+void ILLutil_rselect (
+ int *arr,
+ int l,
+ int r,
+ int m,
+ double *coord,
+ ILLrandstate * rstate)
+{
+ double samplevals[NSAMPLES];
+ int i;
+ int st, en;
+ int n;
+
+ arr += l;
+ n = r - l + 1;
+ m -= l;
+
+ while (n > SORTSIZE)
+ {
+ for (i = 0; i < NSAMPLES; i++)
+ {
+ samplevals[i] = coord[arr[ILLutil_lprand (rstate) % n]];
+ }
+ select_sort_dsample (samplevals, NSAMPLES);
+ select_split (arr, n, samplevals[(NSAMPLES - 1) / 2], &st, &en, coord);
+ if (st > m)
+ {
+ n = st;
+ }
+ else if (en <= m)
+ {
+ arr += en;
+ n -= en;
+ m -= en;
+ }
+ else
+ {
+ return;
+ }
+ }
+
+ select_sort (arr, n, coord);
+ return;
+}
+
+static void select_split (
+ int *arr,
+ int n,
+ double v,
+ int *start,
+ int *end,
+ double *coord)
+{
+ int i, j, k;
+ int t;
+
+ i = 0;
+ j = k = n;
+
+ while (i < j)
+ {
+ if (coord[arr[i]] < v)
+ {
+ i++;
+ }
+ else if (coord[arr[i]] == v)
+ {
+ j--;
+ ILL_SWAP (arr[i], arr[j], t);
+ }
+ else
+ {
+ j--;
+ k--;
+ t = arr[i];
+ arr[i] = arr[j];
+ arr[j] = arr[k];
+ arr[k] = t;
+ }
+ }
+ *start = j;
+ *end = k;
+ return;
+}
+
+static void select_sort (
+ int *arr,
+ int n,
+ double *coord)
+{
+ int i, j;
+ int t;
+
+ for (i = 1; i < n; i++)
+ {
+ t = arr[i];
+ for (j = i; j > 0 && coord[arr[j - 1]] > coord[t]; j--)
+ {
+ arr[j] = arr[j - 1];
+ }
+ arr[j] = t;
+ }
+}
+
+static void select_sort_dsample (
+ double *samp,
+ int n)
+{
+ int i, j;
+ double t;
+
+ for (i = 1; i < n; i++)
+ {
+ t = samp[i];
+ for (j = i; j > 0 && samp[j - 1] > t; j--)
+ {
+ samp[j] = samp[j - 1];
+ }
+ samp[j] = t;
+ }
+}
diff --git a/qsopt_ex/sortrus_common.h b/qsopt_ex/sortrus_common.h
new file mode 100644
index 0000000..c95943f
--- /dev/null
+++ b/qsopt_ex/sortrus_common.h
@@ -0,0 +1,63 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+#ifndef __SORTRUS_H__
+#define __SORTRUS_H__
+/****************************************************************************/
+/* */
+/* sortrus.c */
+/* */
+/****************************************************************************/
+
+#include "urandom.h"
+
+void ILLutil_int_array_quicksort (
+ int *len,
+ int n),
+ ILLutil_int_perm_quicksort (
+ int *perm,
+ int *len,
+ int n),
+ ILLutil_double_perm_quicksort (
+ int *perm,
+ double *len,
+ int n),
+ ILLutil_str_perm_quicksort (
+ int *perm,
+ char **len,
+ int n),
+ ILLutil_rselect (
+ int *arr,
+ int l,
+ int r,
+ int m,
+ double *coord,
+ ILLrandstate * rstate);
+
+char *ILLutil_linked_radixsort (
+ char *data,
+ char *datanext,
+ char *dataval,
+ int valsize);
+
+
+#endif
diff --git a/qsopt_ex/stddefs.h b/qsopt_ex/stddefs.h
new file mode 100644
index 0000000..0200c55
--- /dev/null
+++ b/qsopt_ex/stddefs.h
@@ -0,0 +1,34 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* $RCSfile: stddefs.h,v $ $Revision: 1.3 $ $Date: 2003/11/05 16:57:39 $ */
+#ifndef ILL_STDDEFS_H
+#define ILL_STDDEFS_H
+
+#define SWAP(x,y,temp) {temp = x; x = y; y = temp;}
+
+#define QSMIN(x,y) ((x) < (y) ? (x) : (y))
+#define QSMAX(x,y) ((x) > (y) ? (x) : (y))
+
+#define ABS(x) ((x) >= 0 ? (x) : -(x))
+
+#endif /* ILL_STDDEFS_H */
diff --git a/qsopt_ex/symtab.c b/qsopt_ex/symtab.c
new file mode 100644
index 0000000..0a0eab9
--- /dev/null
+++ b/qsopt_ex/symtab.c
@@ -0,0 +1,969 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCSINFO $Id: symboltab.c,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "eg_mem.h"
+
+#include "logging-private.h"
+
+#include "util.h"
+#include "trace.h"
+#include "except.h"
+#include "symtab.h"
+
+
+static int TRACE = 0;
+
+static unsigned int stringhash (
+ const char *key,
+ int tsize);
+static int look_it_up (
+ ILLsymboltab * h,
+ const char *s);
+static int grow_symboltab (
+ ILLsymboltab * h);
+static int grow_namelist (
+ ILLsymboltab * h);
+static int add_string (
+ ILLsymboltab * h,
+ const char *s,
+ int *symbol);
+static void delete_from_list (
+ ILLsymboltab * h,
+ int del_ind,
+ int prev_ind,
+ int x);
+
+#ifdef TRY_CODE
+/* debug support */
+static const char *get_str (
+ const ILLsymboltab * h,
+ int indx);
+static void prt_xchain (
+ const ILLsymboltab * h,
+ int x);
+static void prt_chain (
+ const ILLsymboltab * h,
+ char *s);
+#endif
+
+
+void ILLsymboltab_init (
+ ILLsymboltab * h)
+{
+ h->tablesize = 0;
+ h->strsize = 0;
+ h->freedchars = 0;
+ h->hashspace = 0;
+ h->name_space = 0;
+ h->strspace = 0;
+ h->hashtable = (int *) NULL;
+ h->nametable = (ILLsymbolent *) NULL;
+ h->namelist = (char *) NULL;
+}
+
+void ILLsymboltab_free (
+ ILLsymboltab * h)
+{
+ ILL_IFFREE (h->hashtable, int);
+
+ ILL_IFFREE (h->nametable, ILLsymbolent);
+ ILL_IFFREE (h->namelist, char);
+
+ ILLsymboltab_init (h);
+}
+
+int ILLsymboltab_create (
+ ILLsymboltab * h,
+ int init_size)
+{
+ int rval = 0;
+ int i;
+
+ if (init_size <= 0)
+ init_size = 1000;
+
+ ILLsymboltab_free (h);
+
+ h->tablesize = 0;
+ h->strsize = 0;
+ h->freedchars = 0;
+ h->name_space = init_size;
+ h->hashspace = ILLutil_nextprime (((unsigned) h->name_space));
+#ifdef TRY_CODE
+ h->strspace = init_size;
+#else
+ h->strspace = init_size * 5;
+#endif
+ h->index_ok = 0;
+
+ ILL_SAFE_MALLOC (h->hashtable, h->hashspace, int);
+
+ ILL_SAFE_MALLOC (h->nametable, h->name_space, ILLsymbolent);
+ ILL_SAFE_MALLOC (h->namelist, h->strspace, char);
+
+ for (i = 0; i < h->hashspace; i++)
+ {
+ h->hashtable[i] = ILL_SYM_NOINDEX;
+ }
+
+CLEANUP:
+ if (rval)
+ {
+ ILLsymboltab_free (h);
+ }
+ ILL_RETURN (rval, "ILLsymboltab_create");
+}
+
+int ILLsymboltab_copy (
+ ILLsymboltab * src,
+ ILLsymboltab * dst)
+{
+ int rval = 0;
+ int i;
+
+ ILLsymboltab_free (dst);
+
+ *dst = *src;
+ ILL_SAFE_MALLOC (dst->hashtable, dst->hashspace, int);
+
+ ILL_SAFE_MALLOC (dst->nametable, dst->name_space, ILLsymbolent);
+ ILL_SAFE_MALLOC (dst->namelist, dst->strspace, char);
+
+ for (i = 0; i < src->hashspace; i++)
+ {
+ dst->hashtable[i] = src->hashtable[i];
+ }
+ for (i = 0; i < src->tablesize; i++)
+ {
+ dst->nametable[i] = src->nametable[i];
+ }
+ for (i = 0; i < src->strsize; i++)
+ {
+ dst->namelist[i] = src->namelist[i];
+ }
+
+CLEANUP:
+ if (rval)
+ {
+ ILLsymboltab_free (dst);
+ }
+ ILL_RETURN (rval, "ILLsymboltab_copy");
+}
+
+
+const char *ILLsymboltab_get (
+ const ILLsymboltab * h,
+ int i)
+{
+ char *name = NULL;
+
+ ILL_FAILfalse_no_rval ((i >= 0) && (i <= h->tablesize), "Index out of range");
+ if (h->nametable[i].symbol != -1)
+ name = h->namelist + h->nametable[i].symbol;
+CLEANUP:
+ return name;
+}
+
+int ILLsymboltab_index_ok (
+ ILLsymboltab * h)
+{
+ return (h && (h->index_ok == 1));
+}
+
+int ILLsymboltab_index_reset (
+ ILLsymboltab * h,
+ int icount,
+ char **names)
+{
+ int rval = 0;
+ int i, k;
+
+ /* Note may have tablesize 1 larger than icount, due to objname */
+
+ if ((h->tablesize != icount) && (h->tablesize != icount + 1))
+ {
+ QSlog("symbol table (%d) does not match reset list (%d)",
+ h->tablesize, icount);
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ for (i = 0; i < icount; i++)
+ {
+ k = look_it_up (h, (const char *) names[i]);
+ if (k)
+ {
+ QSlog("Symbol %s is not in table", names[i]);
+ rval = 1;
+ ILL_CLEANUP;
+ }
+ k = h->the_index;
+ h->nametable[k].index = i;
+ }
+
+ h->index_ok = 1;
+
+CLEANUP:
+ return rval;
+}
+
+int ILLsymboltab_getindex (
+ ILLsymboltab * h,
+ const char *name,
+ int *hindex)
+{
+ int rval = 0;
+ int k;
+
+ *hindex = -1;
+
+ if (!h || !h->index_ok)
+ {
+ QSlog("symbol table index out of date");
+ rval = 1;
+ ILL_CLEANUP;
+ }
+
+ k = look_it_up (h, name);
+ if (k)
+ {
+ QSlog("Symbol %s is not in table", name);
+ ILL_CLEANUP;
+ }
+ k = h->the_index;
+
+ *hindex = h->nametable[k].index;
+
+CLEANUP:
+
+ ILL_RETURN (rval, "ILLsymboltab_getindex");
+}
+
+int ILLsymboltab_rename (
+ ILLsymboltab * h,
+ int i,
+ const char *new_name)
+{
+ int rval = 0;
+ int symbol = 0;
+
+ ILL_FAILfalse ((i >= 0) && (i <= h->tablesize), "Index out of range");
+ if ((new_name != NULL) && (look_it_up (h, new_name) == 0))
+ {
+ rval = (i != h->the_index);
+ ILL_RETURN (rval, "ILLsymboltab_rename");
+ }
+ if (h->nametable[i].symbol != -1)
+ {
+ (void) look_it_up (h, h->namelist + h->nametable[i].symbol);
+ ILL_FAILfalse (i == h->the_index, "must find it at i");
+ delete_from_list (h, i, h->the_prev_index, h->the_hash);
+ }
+ if (new_name != NULL)
+ {
+ rval = add_string (h, new_name, &symbol);
+ ILL_CLEANUP_IF (rval);
+ h->the_hash = stringhash (new_name, h->hashspace);
+ h->nametable[i].symbol = symbol;
+ h->nametable[i].next = h->hashtable[h->the_hash];
+ h->hashtable[h->the_hash] = i;
+ }
+ else
+ {
+ h->nametable[i].symbol = -1;
+ h->nametable[i].next = ILL_SYM_NOINDEX;
+ }
+CLEANUP:
+ ILL_RETURN (rval, "ILLsymboltab_rename");
+}
+
+int ILLsymboltab_lookup (
+ ILLsymboltab * h,
+ const char *s,
+ int *ind)
+{
+ int rval = look_it_up (h, s);
+
+ *ind = h->the_index;
+ return rval;
+}
+
+int ILLsymboltab_contains (
+ ILLsymboltab * tab,
+ const char *name)
+{
+ return !look_it_up (tab, name);
+}
+
+void ILLsymboltab_size (
+ const ILLsymboltab * h,
+ int *p_size)
+{
+ *p_size = h->tablesize;
+}
+
+int ILLsymboltab_register (
+ ILLsymboltab * h,
+ const char *s,
+ int itemindex,
+ int *the_prev_index,
+ int *existed)
+{
+ ILLsymbolent *nametable = h->nametable;
+ int e, symbol = 0;
+ int rval = 0;
+
+ if (itemindex < 0)
+ {
+ h->index_ok = 0;
+ }
+
+ h->the_prev_index = ILL_SYM_NOINDEX;
+ h->the_index = ILL_SYM_NOINDEX;
+ if (s == NULL)
+ {
+ e = h->tablesize;
+ h->the_index = e;
+ *existed = 0;
+ while (h->tablesize >= h->name_space)
+ {
+ rval = grow_symboltab (h);
+ ILL_CLEANUP_IF (rval);
+ }
+ h->tablesize++;
+ h->nametable[e].symbol = -1;
+ h->nametable[e].index = itemindex;
+ h->nametable[e].next = ILL_SYM_NOINDEX;
+ ILL_IFTRACE ("register: %s NULL entry#=%d\n", (*existed) ? "OLD" : "NEW",
+ e);
+ }
+ else
+ {
+ *existed = !look_it_up (h, s);
+ if (*existed)
+ {
+ ILL_IFTRACE ("register: OLD %s entry#=%d hash=%d\n",
+ s, h->the_index, h->the_hash);
+ return 0;
+ }
+
+ rval = add_string (h, s, &symbol);
+ ILL_CLEANUP_IF (rval);
+
+ while (h->tablesize >= h->name_space)
+ {
+ rval = grow_symboltab (h);
+ ILL_CLEANUP_IF (rval);
+ h->the_hash = stringhash (s, h->hashspace); /*hash changes with bigger table */
+ }
+
+ nametable = h->nametable;
+
+ e = h->tablesize;
+ h->tablesize++;
+ h->the_prev_index = e;
+
+ nametable[e].symbol = symbol;
+ nametable[e].index = itemindex;
+ nametable[e].next = h->hashtable[h->the_hash];
+ h->hashtable[h->the_hash] = e;
+
+ ILL_IFTRACE ("register: %s NULL entry#=%d\n", (*existed) ? "OLD" : "NEW",
+ e);
+ }
+
+CLEANUP:
+ *the_prev_index = h->the_prev_index;
+ ILL_RETURN (rval, "ILLsymboltab_register");
+}
+
+int ILLsymboltab_delete (
+ ILLsymboltab * h,
+ const char *s)
+{
+ int del_ind, rval = 0;
+ char *last;
+
+ ILL_FAILtrue (s == NULL, "must give non NULL str");
+
+ rval = look_it_up (h, s);
+ del_ind = h->the_index;
+ ILL_CLEANUP_IF (rval); /* was not in table */
+ ILL_FAILfalse ((del_ind != ILL_SYM_NOINDEX) &&
+ (h->nametable[del_ind].symbol != -1),
+ "we should have found this non NULL str");
+ h->index_ok = 0;
+ delete_from_list (h, del_ind, h->the_prev_index, h->the_hash);
+
+ h->tablesize--;
+ if (del_ind != h->tablesize)
+ {
+ if (h->nametable[h->tablesize].symbol != -1)
+ {
+ last = h->namelist + h->nametable[h->tablesize].symbol;
+ rval = look_it_up (h, last);
+ ILL_FAILfalse ((rval == 0) && (h->the_index == h->tablesize),
+ "Should find last entry");
+ if (h->the_prev_index != ILL_SYM_NOINDEX)
+ {
+ h->nametable[h->the_prev_index].next = del_ind;
+ }
+ else
+ {
+ h->hashtable[h->the_hash] = del_ind;
+ }
+ }
+ h->nametable[del_ind] = h->nametable[h->tablesize];
+ }
+CLEANUP:
+ ILL_RETURN (rval, "ILLsymboltab_delete");
+}
+
+void ILLsymboltab_prt (
+ FILE * fd,
+ ILLsymboltab * h)
+{
+ char *str;
+ int i;
+
+ for (i = 0; i < h->tablesize; i++)
+ {
+ if (h->nametable[i].symbol == -1)
+ {
+ fprintf (fd, "%d: NULL nohash\n", i);
+ }
+ else
+ {
+ str = h->namelist + h->nametable[i].symbol;
+ fprintf (fd, "%d: %s hash=%d\n", i, str, stringhash (str, h->hashspace));
+ }
+ }
+}
+
+static int look_it_up (
+ ILLsymboltab * h,
+ const char *s)
+{
+ ILLsymbolent *nametable = h->nametable;
+ char *namelist = h->namelist;
+ int e;
+
+ if(!h->hashspace) goto CLEANUP;
+ ILL_FAILfalse_no_rval (s, "Should never call with NULL string");
+ h->the_prev_index = ILL_SYM_NOINDEX;
+ h->the_hash = stringhash (s, h->hashspace);
+ for (e = h->hashtable[h->the_hash]; e != ILL_SYM_NOINDEX;
+ e = nametable[e].next)
+ {
+ if (strcmp (namelist + nametable[e].symbol, s) == 0)
+ {
+ h->the_index = e;
+ ILL_IFTRACE ("look_it_up: OLD %s entry#=%d hash=%d\n", s, e, h->the_hash);
+ return 0;
+ }
+ h->the_prev_index = e;
+ }
+CLEANUP:
+ h->the_index = ILL_SYM_NOINDEX;
+ ILL_IFTRACE ("look_it_up: NEW %s \n", s);
+ return 1;
+}
+
+
+static void delete_from_list (
+ ILLsymboltab * h,
+ int del_ind,
+ int prev_ind,
+ int x)
+{
+ if (prev_ind != ILL_SYM_NOINDEX)
+ {
+ ILL_FAILtrue_no_rval (h->nametable[prev_ind].symbol == -1,
+ "A NULL str with same hash ?");
+ h->nametable[prev_ind].next = h->nametable[del_ind].next;
+ }
+ else
+ {
+ h->hashtable[x] = h->nametable[del_ind].next;
+ }
+ h->freedchars += strlen (h->namelist + h->nametable[del_ind].symbol) + 1;
+CLEANUP:
+ ;
+}
+
+
+static int grow_symboltab (
+ ILLsymboltab * h)
+{
+ int newnamespace, newhashspace, *newhash, tablesize;
+ ILLsymbolent *newname;
+ char *namelist = h->namelist;
+ int i;
+ unsigned int x;
+ int rval = 0;
+
+ newnamespace = h->name_space * 2;
+ newhashspace = ILLutil_nextprime (((unsigned) newnamespace));
+ // rval = ILLutil_reallocrus_count ((void **) (&h->nametable), newnamespace,
+ // sizeof (ILLsymbolent));
+ //ILL_CLEANUP_IF (rval);
+ h->nametable = EGrealloc (h->nametable, sizeof (ILLsymbolent) * newnamespace);
+ newname = h->nametable;
+
+ ILL_SAFE_MALLOC (newhash, newhashspace, int);
+ ILL_IFFREE (h->hashtable, int);
+
+ h->hashtable = newhash;
+
+ h->name_space = newnamespace;
+ h->hashspace = newhashspace;
+
+ newhash = h->hashtable;
+ tablesize = h->tablesize;
+
+ for (i = 0; i < newhashspace; i++)
+ {
+ newhash[i] = ILL_SYM_NOINDEX;
+ }
+ for (i = 0; i < tablesize; i++)
+ {
+ if (newname[i].symbol != -1)
+ {
+ x = stringhash (namelist + newname[i].symbol, newhashspace);
+ newname[i].next = newhash[x];
+ newhash[x] = i;
+ }
+ }
+CLEANUP:
+ ILL_RETURN (rval, "grow_symboltab");
+}
+
+static int grow_namelist (
+ ILLsymboltab * h)
+{
+ int newstrspace, i, j, newsymbol, rval = 0;
+ char *newnamelist, *newc;
+
+ if (2 * h->freedchars >= h->strspace)
+ {
+ /* compact string array */
+ ILL_SAFE_MALLOC (newnamelist, h->strspace, char);
+
+ newc = newnamelist;
+ for (i = 0; i < h->tablesize; i++)
+ {
+ if (h->nametable[i].symbol != -1)
+ {
+ newsymbol = newc - newnamelist;
+ for (j = h->nametable[i].symbol; h->namelist[j] != '\0'; j++)
+ {
+ *newc = h->namelist[j];
+ newc++;
+ }
+ *newc = '\0';
+ newc++;
+ h->nametable[i].symbol = newsymbol;
+ }
+ }
+ ILL_IFFREE (h->namelist, char);
+
+ h->namelist = newnamelist;
+ h->strsize = newc - newnamelist;
+ h->freedchars = 0;
+ }
+ else
+ {
+ newstrspace = h->strspace * 2;
+ h->namelist = EGrealloc (h->namelist, sizeof (char) * newstrspace);
+ //rval = ILLutil_reallocrus_count ((void **) &h->namelist, newstrspace,
+ // sizeof (char));
+ //ILL_CLEANUP_IF (rval);
+ h->strspace = newstrspace;
+ }
+CLEANUP:
+ ILL_RETURN (rval, "grow_namelist");
+}
+
+static int add_string (
+ ILLsymboltab * h,
+ const char *s,
+ int *symbol)
+{
+ int l, rval = 0;
+
+ l = strlen (s) + 1;
+ while (h->strsize + l > h->strspace)
+ {
+ rval = grow_namelist (h);
+ ILL_CLEANUP_IF (rval);
+ }
+ strcpy (h->namelist + h->strsize, s);
+ *symbol = h->strsize;
+ h->strsize += l;
+CLEANUP:
+ ILL_RETURN (rval, "add_string");
+}
+
+static unsigned int stringhash (
+ const char *key,
+ int tsize)
+{
+ unsigned int x = 0;
+
+#ifdef TRY_CODE
+ while (*key)
+ {
+ x += *key;
+ key++;
+ }
+#else
+ while (*key)
+ {
+ x = 37 * x + *key;
+ key++;
+ }
+#endif
+ return x % tsize;
+}
+
+/**************************************************************************/
+/* ILLsymboltab_unique_name and its support */
+/**************************************************************************/
+static void make_var (
+ char *new_var,
+ const char *prefix,
+ char *name)
+{
+ size_t plen = strlen (prefix);
+ size_t nlen = strlen (name);
+ char *p;
+
+ if (nlen + plen >= ILL_namebufsize)
+ {
+ nlen = ILL_namebufsize - plen - 1;
+ }
+ strcpy (new_var, prefix);
+ p = new_var + plen;
+ strncpy (p, name, nlen + 1);
+}
+
+int ILLsymboltab_uname (
+ ILLsymboltab * symtab,
+ char *name,
+ const char *try_prefix1,
+ const char *try_prefix2)
+{
+ int nvars = symtab->tablesize;
+ int rval = 0;
+ int i, found, numlen;
+ const char *try_prefix[3];
+ char prefix[ILL_namebufsize];
+ char new_pre[ILL_namebufsize];
+ char new[ILL_namebufsize];
+
+ ILL_FAILtrue (try_prefix1 == NULL, "try_prefix must not be NULL");
+ try_prefix[0] = try_prefix1;
+ try_prefix[1] = try_prefix2;
+ try_prefix[2] = NULL;
+ new[0] = '\0';
+ found = 0;
+ for (i = 0; (!found) && try_prefix[i]; i++)
+ {
+ make_var (new, try_prefix[i], name);
+ found = !ILLsymboltab_contains (symtab, new);
+ }
+ if (!found)
+ {
+ i = 0;
+ sprintf (prefix, "%s", try_prefix[0]);
+ numlen = (log10 ((double) (symtab->tablesize - 1) * 10)) + 1;
+ while (!found)
+ {
+ ILL_FAILfalse (i <= nvars, "something wrong in find_unique_name");
+ make_var (new_pre, prefix, name);
+ new_pre[ILL_namebufsize - numlen - 1] = '\0';
+ sprintf (new, "%s_%d", new_pre, i);
+ found = !ILLsymboltab_contains (symtab, new);
+ i++;
+ }
+ }
+
+CLEANUP:
+ strcpy (name, new);
+ return rval;
+}
+
+void ILLsymboltab_unique_name (
+ ILLsymboltab * tab,
+ int i,
+ const char *pref,
+ char uname2[ILL_namebufsize])
+{
+ int notUnique;
+
+ sprintf (uname2, "%d", i);
+ notUnique = ILLsymboltab_uname (tab, uname2, pref, NULL);
+ ILL_FAILtrue_no_rval (notUnique, "Programming error");
+CLEANUP:
+ return;
+}
+
+#ifdef TRY_CODE
+/* debugging */
+static const char *get_str (
+ const ILLsymboltab * h,
+ int indx)
+{
+ if (indx < 0 || indx >= h->tablesize)
+ {
+ return "INDEX OUT OF RANGE";
+ }
+ if (h->nametable[indx].symbol == -1)
+ {
+ return "NULL";
+ }
+ else
+ {
+ return h->namelist + h->nametable[indx].symbol;
+ }
+}
+
+static void prt_xchain (
+ const ILLsymboltab * h,
+ int x)
+{
+ int e;
+ char *str;
+
+ x = x % h->hashspace;
+ QSlog("chain hash %d:", x);
+ for (e = h->hashtable[x]; e != ILL_SYM_NOINDEX; e = h->nametable[e].next)
+ {
+ if (h->nametable[e].symbol >= 0)
+ {
+ str = h->namelist + h->nametable[e].symbol;
+ x = stringhash (str, h->hashspace);
+ QSlog(" %s(h=%d, e=%d)", str, x, e);
+ }
+ else
+ {
+ QSlog(" NULL");
+ }
+ }
+}
+
+static void prt_chain (
+ const ILLsymboltab * h,
+ char *s)
+{
+ int e;
+
+ if (s != NULL)
+ {
+ prt_xchain (h, stringhash (s, h->hashspace));
+ }
+ else
+ {
+ for (e = 0; e < h->hashspace; e++)
+ {
+ if (h->hashtable[e] != ILL_SYM_NOINDEX)
+ prt_xchain (h, e);
+ }
+ }
+}
+#endif
+
+#ifdef TRY_CODE
+int main (
+ int ac,
+ char **av)
+{
+
+ int i, rval, index, pre_exist, nwords;
+ const char *prefix[3];
+ ILLsymboltab t, *tab = &t;
+ char cmd[100], symbol[100], line[256], str[100];
+ const char *s;
+ int ok;
+
+ TRACE = 1;
+ prefix[0] = "C";
+ prefix[1] = "c";
+ prefix[2] = NULL;
+ ILLsymboltab_init (tab);
+ ILLsymboltab_create (tab, 1);
+
+ fprintf (stdout, "> ");
+ fflush (stdout);
+ while (fgets (line, 100, stdin))
+ {
+ ok = 0;
+ symbol[0] = '\0';
+ nwords = sscanf (line, "%s%s%s", cmd, symbol, str);
+ if (nwords >= 1)
+ {
+ fprintf (stdout, ":: %s", line);
+ if ((nwords >= 2) && strcmp (cmd, "REG") == 0)
+ {
+ ok = 1;
+ if (strcmp (symbol, "NULL") == 0)
+ {
+ rval = ILLsymboltab_register (tab, NULL, &index, &pre_exist);
+ }
+ else
+ {
+ rval = ILLsymboltab_register (tab, symbol, &index, &pre_exist);
+ }
+ }
+ if ((nwords >= 2) && strcmp (cmd, "LOOK") == 0)
+ {
+ ok = 1;
+ rval = ILLsymboltab_register (tab, symbol, &index, &pre_exist);
+ }
+ if ((nwords >= 2) && strcmp (cmd, "DEL") == 0)
+ {
+ ok = 1;
+ rval = ILLsymboltab_delete (tab, symbol);
+ }
+ if ((nwords >= 2) && strcmp (cmd, "UNIQUE") == 0)
+ {
+ ok = 1;
+ rval = ILLsymboltab_uname (tab, symbol, "c", "C");
+ }
+ if ((nwords >= 1) && strcmp (cmd, "PRT") == 0)
+ {
+ ok = 1;
+ ILLsymboltab_prt (stdout, tab);
+ }
+ if ((nwords >= 2) && strcmp (cmd, "GET") == 0)
+ {
+ ok = 1;
+ i = atoi (symbol);
+ s = ILLsymboltab_get (tab, i);
+ fprintf (stdout, "%d: %s\n", i, (s != NULL) ? s : "NULL");
+ }
+ if ((nwords >= 3) && strcmp (cmd, "RENAME") == 0)
+ {
+ ok = 1;
+ i = atoi (symbol);
+ if (strcmp (str, "NULL") == 0)
+ {
+ ILLsymboltab_rename (tab, i, NULL);
+ }
+ else
+ {
+ ILLsymboltab_rename (tab, i, str);
+ }
+ }
+ if (strcmp (cmd, "CHAIN") == 0)
+ {
+ ok = 1;
+ if ((nwords == 1) || strcmp (symbol, "NULL") == 0)
+ {
+ prt_chain (tab, NULL);
+ fprintf (stdout,
+ "last %s(%d) strsize/space: %d/%d freedchars: %d\n",
+ get_str (tab, tab->tablesize - 1), tab->tablesize - 1,
+ tab->strsize, tab->strspace, tab->freedchars);
+ }
+ else
+ {
+ prt_chain (tab, symbol);
+ }
+ }
+ if ((nwords >= 1) && strcmp (cmd, "INFO") == 0)
+ {
+ ok = 1;
+ fprintf (stdout,
+ "last %s(%d) strsize/space: %d/%d freedchars: %d\n",
+ get_str (tab, tab->tablesize - 1), tab->tablesize - 1,
+ tab->strsize, tab->strspace, tab->freedchars);
+ }
+ if ((nwords >= 1) && strcmp (cmd, "STR") == 0)
+ {
+ ok = 1;
+ for (i = 0; i < tab->strsize; i++)
+ {
+ if (tab->namelist[i] == '\0')
+ fprintf (stdout, "\\0");
+ else
+ fprintf (stdout, "%c", tab->namelist[i]);
+ }
+ fprintf (stdout, "\n");
+ }
+ }
+ if (ok == 0)
+ {
+ fprintf (stdout, "commands: REG, LOOK, DEL, RENAME, GET, %s\n",
+ "RENAME, UNIQUE, CHAIN, STR, INFO, PRT");
+ }
+ fprintf (stdout, "> ");
+ fflush (stdout);
+ }
+
+ return 0;
+}
+
+/* sample input for testing symboltab */
+#ifdef NEVER
+REG aabb REG aabb // its already there
+ REG abab REG abab // its already there
+ REG baba REG baba // its already there
+ REG bbaa REG bbaa // its already there
+ CHAIN aabb STR // all with same hash
+ DEL abab // remove from middle
+ CHAIN baba DEL aabb // remove last
+ CHAIN baba DEL bbaa // remove first
+ CHAIN baba DEL baba // remove the only element
+ CHAIN PRT STR REG 123456789012 // compact name list no entries in table
+ STR REG longnametoo INFO REG a REG b DEL 123456789012 DEL longnametoo INFO STR REG more // compact name list with entries in table
+ STR INFO PRT REG NULL // add NULL str
+ PRT DEL b // remove with NULL being last entry
+ PRT CHAIN DEL a // remove with NULL somewhere in table
+ PRT DEL more CHAIN // nothing left in table
+ REG NULL // add NULL str
+ REG NULL // add NULL str
+ REG NULL // add NULL str
+ REG more PRT CHAIN // only chain is for more
+ RENAME 0 more // should fail
+ RENAME 0 another // own hash
+ RENAME 0 another // must fail
+ CHAIN RENAME 1 orem // existing hash
+ CHAIN RENAME 2 makestrarraygrowevenlongerwiththisid CHAIN PRT INFO STR DEL makestrarraygrowevenlongerwiththisid STR RENAME 3 somemore // should trigger grownamelist
+
+ PRT
+ REG omemore
+ STR
+ CHAIN
+ INFO
+ UNIQUE a
+ UNIQUE a
+ REG Ca
+ UNIQUE a REG ca UNIQUE a REG Ca_0 REG Ca_1 REG Ca_2 REG Ca_3 REG Ca_4 UNIQUE a
+#endif
+#endif
diff --git a/qsopt_ex/symtab.h b/qsopt_ex/symtab.h
new file mode 100644
index 0000000..3ce795d
--- /dev/null
+++ b/qsopt_ex/symtab.h
@@ -0,0 +1,141 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCSINFO $Id: symtab.h,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+#ifndef ILL_SYMTAB_H
+#define ILL_SYMTAB_H
+
+#include <stdlib.h>
+#include <stdio.h>
+
+/* we allow 256KB of buffer space i.e. 2^17*/
+#define ILL_namebufsize 0x20000U
+
+typedef struct ILLsymbolent
+{
+ int symbol;
+ int index;
+ int next;
+}
+ILLsymbolent;
+
+typedef struct ILLsymboltab
+{
+ int *hashtable;
+ ILLsymbolent *nametable;
+ char *namelist;
+ int tablesize;
+ int strsize;
+ int hashspace;
+ int name_space;
+ int strspace;
+ int freedchars;
+ int the_hash;
+ int the_index;
+ int the_prev_index;
+ int index_ok;
+}
+ILLsymboltab;
+
+/*
+ * hashtable[stringhash(entry) % hashspace] either NO_INDEX or some hash number
+ * nametable[hash number] = { next: another index for nametable
+ * symbol: index into namelist where string resides
+ * }
+ * tablesize: number of entries (tablesize <= name_space)
+ * name_space: length of nametable and indexlist
+ * hashspace: length of hashtable nextprime(name_space)
+ * strsize: number of chars used in namelist
+ * strspace: length of namelist
+ * indexlist: LP col/row indices for the table entries
+ * indexlist_ok: 1 if column indices in indexlist are up-to-date, 0 otherwise
+ *
+ * Deletion of entries affects their ordering in symboltab->nametable.
+ * Strings may move around within symboltab->namelist.
+ */
+
+
+#define ILL_SYM_NOINDEX (-1)
+extern void ILLsymboltab_init (
+ ILLsymboltab * h),
+ ILLsymboltab_free (
+ ILLsymboltab * h),
+ ILLsymboltab_size (
+ const ILLsymboltab * h,
+ int *p_size),
+ ILLsymboltab_prt (
+ FILE * fd,
+ ILLsymboltab * h);
+
+extern int ILLsymboltab_create (
+ ILLsymboltab * h,
+ int init_size),
+ ILLsymboltab_copy (
+ ILLsymboltab * src,
+ ILLsymboltab * dst),
+ ILLsymboltab_register (
+ ILLsymboltab * h,
+ const char *s,
+ int itemindex,
+ int *p_index,
+ int *p_existed),
+ ILLsymboltab_lookup (
+ ILLsymboltab * h,
+ const char *s,
+ int *p_index),
+ ILLsymboltab_index_ok (
+ ILLsymboltab * h),
+ ILLsymboltab_index_reset (
+ ILLsymboltab * h,
+ int icount,
+ char **names),
+ ILLsymboltab_getindex (
+ ILLsymboltab * h,
+ const char *name,
+ int *hindex),
+ ILLsymboltab_contains (
+ ILLsymboltab * h,
+ const char *s),
+ ILLsymboltab_delete (
+ ILLsymboltab * h,
+ const char *s),
+ ILLsymboltab_uname (
+ ILLsymboltab * h,
+ char name[ILL_namebufsize],
+ const char *try_prefix1,
+ const char *try_prefix2);
+
+extern void ILLsymboltab_unique_name (
+ ILLsymboltab * tab,
+ int i,
+ const char *pref,
+ char uname[ILL_namebufsize]);
+
+extern const char *ILLsymboltab_get (
+ const ILLsymboltab * tab,
+ int i);
+extern int ILLsymboltab_rename (
+ ILLsymboltab * h,
+ int i,
+ const char *new_name);
+
+#endif /* __SYMTAB_H */
diff --git a/qsopt_ex/trace.h b/qsopt_ex/trace.h
new file mode 100644
index 0000000..158fe0b
--- /dev/null
+++ b/qsopt_ex/trace.h
@@ -0,0 +1,41 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCSINFO $Id: trace.h,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+#ifndef ILL_trace_h
+#define ILL_trace_h
+
+#include "logging-private.h"
+
+/* users of these macros must declare a static int TRACE variable */
+#ifndef NDEBUG
+#define ILL_IFTRACE if (TRACE) QSlog
+#define ILL_IFTRACE2 if (TRACE > 1) QSlog
+#define ILL_IFDOTRACE if (TRACE)
+#else
+/* the optimizer will take care of this */
+#define ILL_IFTRACE if (0) QSlog
+#define ILL_IFTRACE if (0) QSlog
+#define ILL_IFDOTRACE if (0)
+#endif
+
+#endif
diff --git a/qsopt_ex/urandom.c b/qsopt_ex/urandom.c
new file mode 100644
index 0000000..75062ea
--- /dev/null
+++ b/qsopt_ex/urandom.c
@@ -0,0 +1,169 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCSINFO $Id: urandom.c,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+/****************************************************************************/
+/* */
+/* This file is part of CONCORDE */
+/* */
+/* (c) Copyright 1995--1999 by David Applegate, Robert Bixby, */
+/* Vasek Chvatal, and William Cook */
+/* */
+/* Permission is granted for academic research use. For other uses, */
+/* contact the authors for licensing options. */
+/* */
+/* Use at your own risk. We make no guarantees about the */
+/* correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* MACHINE INDEPENDENT RANDOM NUMBER GENERATOR */
+/* */
+/* TSP CODE */
+/* */
+/* */
+/* Written by: DIMACS (modified for TSP) */
+/* Date: February 7, 1995 (cofeb16) */
+/* */
+/* */
+/* EXPORTED FUNCTIONS: */
+/* */
+/* void ILLutil_sprand (int seed, ILLrandstate *r) */
+/* - Call once to initialize the generator. */
+/* */
+/* int ILLutil_lprand (QSrandstate *r) */
+/* - Returns an integer in the range 0 to ILL_PRANDMAX - 1. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* NOTES (from DIMACS): */
+/* This file contains a set of c-language functions for generating */
+/* uniform integers. This is a COMPLETELY PORTABLE generator. It will */
+/* give IDENTICAL sequences of random numbers for any architecture with */
+/* at least 30-bit integers, regardless of the integer representation, */
+/* INT_MAX value, or roundoff/truncation method, etc. */
+/* This Truly Remarkable RNG is described more fully in */
+/* J. Bentley's column, ``The Software Exploratorium ''. It is based on */
+/* one in Knuth, Vol 2, Section 3.2.2 (Algorithm A). */
+/* */
+/****************************************************************************/
+
+
+#include "util.h"
+
+
+void ILLutil_sprand (
+ int seed,
+ ILLrandstate * r)
+{
+ int i, ii;
+ int last, next;
+ int *arr = r->arr;
+
+ arr[0] = last = seed;
+ next = 1;
+ for (i = 1; i < 55; i++)
+ {
+ ii = (21 * i) % 55;
+ arr[ii] = next;
+ next = last - next;
+ if (next < 0)
+ next += ILL_PRANDMAX;
+ last = arr[ii];
+ }
+ r->a = 0;
+ r->b = 24;
+ for (i = 0; i < 165; i++)
+ last = ILLutil_lprand (r);
+}
+
+
+int ILLutil_lprand (
+ ILLrandstate * r)
+{
+ int t;
+
+ if (r->a-- == 0)
+ r->a = 54;
+ if (r->b-- == 0)
+ r->b = 54;
+
+ t = r->arr[r->a] - r->arr[r->b];
+
+ if (t < 0)
+ t += ILL_PRANDMAX;
+
+ r->arr[r->a] = t;
+
+ return t;
+}
+
+
+#ifdef TRY_CODE
+
+/*-----------------------------------------------*/
+/* This is a little driver program so you can */
+/* test the code. */
+/* Typing: a.out 0 3 1 */
+/* should produce */
+/* 921674862 */
+/* 250065336 */
+/* 377506581 */
+/* Typing: a.out 1000000 1 2 */
+/* should produce */
+/* 57265995 */
+/*-----------------------------------------------*/
+
+int main (
+ int ac,
+ char **av)
+{
+ int i;
+ int j;
+ int n;
+ int m;
+ int seed;
+ ILLrandstate rstate;
+
+ if (ac < 4)
+ {
+ fprintf (stderr, "Usage: #discard #print #seed\n");
+ return 0;
+ }
+ m = atoi (av[1]); /* Number to discard initially */
+ n = atoi (av[2]); /* Number to print */
+ seed = atoi (av[3]); /* Seed */
+
+ ILLutil_sprand (seed, &rstate);
+
+ for (i = 0; i < m; i++)
+ j = ILLutil_lprand (&rstate);
+ for (i = 0; i < n; i++)
+ printf ("%ld\n", ILLutil_lprand (&rstate));
+ return 0;
+}
+
+#endif /* TRY_CODE */
diff --git a/qsopt_ex/urandom.h b/qsopt_ex/urandom.h
new file mode 100644
index 0000000..dc298ac
--- /dev/null
+++ b/qsopt_ex/urandom.h
@@ -0,0 +1,59 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+#ifndef __URANDOM_H__
+#define __URANDOM_H__
+/****************************************************************************/
+/* */
+/* urandom.c */
+/* */
+/****************************************************************************/
+
+/* since urandom's generator does everything modulo ILL_PRANDMAX, if two
+ * seeds are congruent mod x and x|ILL_PRANDMAX, then the resulting numbers
+ * will be congruent mod x. One example was if ILL_PRANDMAX = 1000000000 and
+ * urandom is used to generate a point set from a 1000x1000 grid, seeds
+ * congruent mod 1000 generate the same point set.
+ *
+ * For this reason, we use 1000000007 (a prime)
+ */
+#define ILL_PRANDMAX 1000000007
+
+typedef struct ILLrandstate
+{
+ int a;
+ int b;
+ int arr[55];
+}
+ILLrandstate;
+
+
+void ILLutil_sprand (
+ int seed,
+ ILLrandstate * r);
+
+int ILLutil_lprand (
+ ILLrandstate * r);
+
+
+
+#endif
diff --git a/qsopt_ex/util.c b/qsopt_ex/util.c
new file mode 100644
index 0000000..b9bb67b
--- /dev/null
+++ b/qsopt_ex/util.c
@@ -0,0 +1,283 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCSINFO $Id: util.c,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+/****************************************************************************/
+/* */
+/* This file is part of CONCORDE */
+/* */
+/* (c) Copyright 1995--1999 by David Applegate, Robert Bixby, */
+/* Vasek Chvatal, and William Cook */
+/* */
+/* Permission is granted for academic research use. For other uses, */
+/* contact the authors for licensing options. */
+/* */
+/* Use at your own risk. We make no guarantees about the */
+/* correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* MISCELLANEOUS UTILITY ROUTINES */
+/* */
+/* TSP CODE */
+/* */
+/* Written by: Applegate, Bixby, Chvatal, and Cook */
+/* Date: October 12, 1995 */
+/* Date: September 28, 1997 */
+/* */
+/* EXPORTED FUNCTIONS: */
+/* */
+/* unsigned int ILLutil_nextprime (unsigned int x) */
+/* FINDS the smallest positive prime >= x */
+/* */
+/* int ILLutil_our_gcd (int a, int b) */
+/* COMPUTES gcd(a,b) */
+/* -gcd(a,b) is always >= 0 */
+/* -a and b can be negative, positive, or zero */
+/* */
+/* int ILLutil_our_lcm (int a, int b) */
+/* COMPUTES lcm(a,b) */
+/* -lcm(a,b) is always >= 0 */
+/* -a and b can be negative, positive, or zero */
+/* */
+/* double ILLutil_our_floor (double x) */
+/* REURNS the greatest integer no larger than x. */
+/* */
+/* double ILLutil_our_ceil (double x) */
+/* REURNS the least integer no smaller than x. */
+/* */
+/* double ILLutil_our_frac (double x) */
+/* REURNS the fractional part of x. */
+/* */
+/* char *ILLutil_strchr (const char *s, int c) */
+/* RETURNS a pointer to the first occurrence of c in s, or NULL if c */
+/* does not occur in s */
+/* */
+/* int ILLutil_strcasecmp(const char *s1, const char *s2) */
+/* RETURNS the string comparison, iqnoring the case of the letters. */
+/* */
+/* int ILLutil_strncasecmp(const char *s1, const char *s2, size_t n) */
+/* RETURNS the string comparision, iqnoring case, looks at max n bytes. */
+/* */
+/* char *ILLutil_str(const char *s) */
+/* allocates and returns a copy of s */
+/* */
+/****************************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+
+#include "except.h"
+#include "util.h"
+
+
+static int isprime (
+ unsigned int x);
+
+
+unsigned int ILLutil_nextprime (
+ unsigned int x)
+{
+ if (x < 3)
+ return 3;
+ x |= 1;
+ while (!isprime (x))
+ x += 2;
+ return x;
+}
+
+static int isprime (
+ unsigned int p)
+{
+ unsigned int i;
+
+ if ((p & 1) == 0)
+ return 0;
+ for (i = 3; i * i <= p; i += 2)
+ {
+ if (p % i == 0)
+ return 0;
+ }
+ return 1;
+}
+
+int ILLutil_our_gcd (
+ int a,
+ int b)
+{
+ int c;
+
+ if (a < 0)
+ a = -a;
+ if (b < 0)
+ b = -b;
+ if (a > b)
+ ILL_SWAP (a, b, c);
+
+ while (a)
+ {
+ c = b % a;
+ b = a;
+ a = c;
+ }
+ return b;
+}
+
+int ILLutil_our_lcm (
+ int a,
+ int b)
+{
+ int c;
+
+ if (a < 0)
+ a = -a;
+ if (b < 0)
+ b = -b;
+
+ c = ILLutil_our_gcd (a, b);
+
+ return (a / c) * b;
+}
+
+double ILLutil_our_floor (
+ double x)
+{
+ return floor (x);
+}
+
+double ILLutil_our_ceil (
+ double x)
+{
+ return ceil (x);
+}
+
+double ILLutil_our_frac (
+ double x)
+{
+ return x - floor (x);
+}
+
+double ILLutil_norm_sqr (
+ double *v,
+ int len)
+{
+ int i;
+ double sum = 0.0;
+
+ for (i = 0; i < len; i++)
+ sum += v[i] * v[i];
+ return sum;
+}
+
+int ILLutil_our_log2 (
+ int a)
+{
+ int i = 0, j = 1;
+
+ while (j < a)
+ {
+ j = j << 1;
+ i++;
+ }
+ return i ? i : 1;
+}
+
+const char *ILLutil_strchr (
+ const char *s,
+ int c)
+{
+ while (*s)
+ {
+ if (*s == c)
+ return s;
+ s++;
+ }
+ return (char *) NULL;
+}
+
+int ILLutil_strcasecmp (
+ const char *s1,
+ const char *s2)
+{
+ return strcasecmp (s1, s2);
+}
+
+int ILLutil_strncasecmp (
+ const char *s1,
+ const char *s2,
+ size_t n)
+{
+ return strncasecmp (s1, s2, n);
+}
+
+int ILLutil_index (
+ const char *list[],
+ const char *name)
+{
+ int i;
+
+ for (i = 0; list[i] != NULL; i++)
+ {
+ if (!strcmp (name, list[i]))
+ {
+ return i;
+ }
+ }
+ return -1;
+}
+
+int ILLutil_array_index (
+ char *list[],
+ int n,
+ const char *name)
+{
+ int i;
+
+ for (i = 0; i < n; i++)
+ {
+ if ((list[i] != NULL) && !strcmp (name, list[i]))
+ {
+ return i;
+ }
+ }
+ return -1;
+}
+
+char *ILLutil_str (
+ const char *str)
+{
+ int len;
+ char *cpy = NULL;
+
+ if (str != NULL)
+ {
+ len = strlen (str) + 1;
+ ILL_SAFE_MALLOC_no_rval (cpy, len, char);
+
+ strcpy (cpy, str);
+ }
+CLEANUP:
+ return cpy;
+}
diff --git a/qsopt_ex/util.h b/qsopt_ex/util.h
new file mode 100644
index 0000000..f6021b7
--- /dev/null
+++ b/qsopt_ex/util.h
@@ -0,0 +1,152 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCSINFO $Id: util.h,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+#ifndef ILL_UTIL_H
+#define ILL_UTIL_H
+
+#ifdef _USRDLL
+
+#ifdef QSLIB_EXPORTS
+#define QSLIB_INTERFACE __declspec(dllexport)
+#else
+#define QSLIB_INTERFACE __declspec(dllimport)
+#endif
+
+#else
+
+#define QSLIB_INTERFACE extern
+
+#endif
+
+#ifdef WIN32
+#define strcasecmp(s1, s2) stricmp(s1, s2)
+#define strncasecmp(s1, s2, n) strnicmp(s1, s2, n)
+#endif
+
+/****************************************************************************/
+/* */
+/* This file is part of CONCORDE */
+/* */
+/* (c) Copyright 1995--1999 by David Applegate, Robert Bixby, */
+/* Vasek Chvatal, and William Cook */
+/* */
+/* Permission is granted for academic research use. For other uses, */
+/* contact the authors for licensing options. */
+/* */
+/* Use at your own risk. We make no guarantees about the */
+/* correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* EXPORTED FUNCTIONS: */
+/* */
+/* EGLPNUMPT_SWAP */
+/* ILL_SWAP(a,b,t) */
+/* swaps a and b, using t as temporary space. a, b, and t should all */
+/* be the same type. */
+/* */
+/* ILL_OURABS(a) */
+/* returns the absolute value of a. */
+/* */
+/****************************************************************************/
+typedef char ILLbool;
+
+#define FALSE 0
+#define TRUE 1
+
+#define ILL_SWAP(a,b,t) (((t)=(a)),((a)=(b)),((b)=(t)))
+
+#define ILL_OURABS(a) (((a) >= 0) ? (a) : -(a))
+
+#include "sortrus_common.h"
+#include "allocrus.h"
+#include "urandom.h"
+#include "zeit.h"
+/****************************************************************************/
+/* */
+/* util.c */
+/* */
+/****************************************************************************/
+#define ILL_UTIL_STR(new, str) \
+ { new = ILLutil_str(str); \
+ if (str != NULL) { ILL_CHECKnull(new, "out of memeory"); } }
+
+extern char *ILLutil_str (
+ const char *str);
+
+ /* allocates and returns a copy of s */
+
+extern int ILLutil_array_index (
+ char *list[],
+ int n,
+ const char *name);
+
+ /* returns index of name in list or -1 */
+
+extern int ILLutil_index (
+ const char *list[],
+ const char *name);
+
+ /* returns index of name in list or -1 */
+
+extern unsigned int ILLutil_nextprime (
+ unsigned int x);
+
+extern const char *ILLutil_strchr (
+ const char *s,
+ int c);
+
+extern int ILLutil_strcasecmp (
+ const char *s1,
+ const char *s2);
+extern int ILLutil_strncasecmp (
+ const char *s1,
+ const char *s2,
+ size_t n);
+
+
+extern int ILLutil_our_gcd (
+ int a,
+ int b),
+ ILLutil_our_lcm (
+ int a,
+ int b),
+ ILLutil_our_log2 (
+ int a);
+
+double ILLutil_our_floor (
+ double x),
+ ILLutil_our_ceil (
+ double x),
+ ILLutil_our_frac (
+ double x),
+ ILLutil_norm_sqr (
+ double *v,
+ int len);
+
+#include "bgetopt.h"
+/*#include "dheaps_i.h"*/
+/*#include "priority.h"*/
+#endif /* ILL_UTIL_H */
diff --git a/qsopt_ex/write_lp.c b/qsopt_ex/write_lp.c
new file mode 100644
index 0000000..f03c6ce
--- /dev/null
+++ b/qsopt_ex/write_lp.c
@@ -0,0 +1,262 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: wr_lp.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+
+/****************************************************************************/
+/* */
+/* Routines to support writing of LP files */
+/* */
+/****************************************************************************/
+
+/*
+ * -) anything after '\' is comment
+ * -) variables consist of a-z A-Z 0-9!"#$%(),;.?@_`'{}|~
+ * don't start with a digit or '.'
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "logging-private.h"
+
+#include "eg_lpnum.h"
+#include "eg_io.h"
+#include "except.h"
+
+#include "lpdefs_EGLPNUM_TYPENAME.h"
+#include "write_lp_EGLPNUM_TYPENAME.h"
+
+
+void EGLPNUM_TYPENAME_ILLwrite_lp_state_init (
+ EGLPNUM_TYPENAME_ILLwrite_lp_state * line,
+ const char *str)
+{
+ line->total = 0;
+ line->p = line->buf;
+ *line->p = '\0';
+ if (str != NULL)
+ {
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, str);
+ }
+}
+
+void EGLPNUM_TYPENAME_ILLwrite_lp_state_append (
+ EGLPNUM_TYPENAME_ILLwrite_lp_state * line,
+ const char *str)
+{
+ int len, rval = 0;
+
+ ILL_FAILfalse (str, "Must have non NULL string");
+ sprintf (line->p, "%s", str);
+ len = strlen (line->p);
+ line->total += len;
+ line->p += len;
+CLEANUP:
+ return;
+}
+
+void EGLPNUM_TYPENAME_ILLwrite_lp_state_append_coef (
+ EGLPNUM_TYPENAME_ILLwrite_lp_state * line,
+ EGLPNUM_TYPE v,
+ int cnt)
+{
+ EGLPNUM_TYPE ntmp;
+ int len = 0;
+
+ EGLPNUM_TYPENAME_EGlpNumInitVar (ntmp);
+ EGLPNUM_TYPENAME_EGlpNumCopy (ntmp, v);
+ if (EGLPNUM_TYPENAME_EGlpNumIsLessZero (ntmp))
+ {
+ sprintf (line->p, " - ");
+ len = 3;
+ EGLPNUM_TYPENAME_EGlpNumSign (ntmp);
+ }
+ else
+ {
+ if (cnt > 0)
+ {
+ sprintf (line->p, " + ");
+ len = 3;
+ }
+ else
+ {
+ sprintf (line->p, " ");
+ len = 1;
+ }
+ }
+ line->p += len;
+ line->total += len;
+ if (EGLPNUM_TYPENAME_EGlpNumIsNeqq (ntmp, EGLPNUM_TYPENAME_oneLpNum))
+ {
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append_number (line, ntmp);
+ }
+ EGLPNUM_TYPENAME_EGlpNumClearVar (ntmp);
+}
+
+/* so that diff will not stumble over too many number format differences
+ * between c and java generated lp files we make here sure that doubles
+ * which are printed without a ".xxx" part get ".0" from us
+ */
+static void append_number (
+ EGLPNUM_TYPENAME_ILLwrite_lp_state * line,
+ EGLPNUM_TYPE v);
+void EGLPNUM_TYPENAME_ILLwrite_lp_state_append_number (
+ EGLPNUM_TYPENAME_ILLwrite_lp_state * line,
+ EGLPNUM_TYPE v)
+{
+ /* write a blank after 'inf' in case it is used as a coefficient and
+ * a variable follows */
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (v, EGLPNUM_TYPENAME_ILL_MAXDOUBLE))
+ {
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, "inf ");
+ }
+ else
+ {
+ if (EGLPNUM_TYPENAME_EGlpNumIsEqqual (v, EGLPNUM_TYPENAME_ILL_MINDOUBLE))
+ {
+ EGLPNUM_TYPENAME_ILLwrite_lp_state_append (line, "-inf ");
+ }
+ else
+ append_number (line, v);
+ }
+}
+
+static void append_number (
+ EGLPNUM_TYPENAME_ILLwrite_lp_state * line,
+ EGLPNUM_TYPE v)
+{
+ int len = 0;
+ char *numstr = EGLPNUM_TYPENAME_EGlpNumGetStr (v);
+
+ sprintf (line->p, "%s%n", numstr, &len);
+ EGfree (numstr);
+ line->p += len;
+ line->total += len;
+}
+
+#if 0
+#define D_SCALE (1e9)
+static void append_number (
+ EGLPNUM_TYPENAME_ILLwrite_lp_state * line,
+ double x)
+{
+ /* Better code for writing rational problems */
+ int i, k;
+ int got = 0;
+ double w, t;
+ int nnum = 0;
+ int nden = 0;
+
+ if (x != 0.0)
+ {
+ if (x < 0.0)
+ w = -x;
+ else
+ w = x;
+
+ for (i = -9, t = 0.000000001; i <= 7; i++, t *= 10.0)
+ {
+ if (w >= t && w <= t * 10)
+ {
+ got = 1;
+ break;
+ }
+ }
+ if (got == 0)
+ {
+ QSlog("Out-of-range number: %f", x);
+ exit (1);
+ }
+ }
+
+ if (x < 0.0)
+ {
+ sprintf (line->p, "-");
+ line->p++;
+ line->total++;
+ x = -x;
+ }
+
+ while (x >= 10.0 * D_SCALE)
+ {
+ x /= 10.0;
+ nnum++;
+ }
+
+ /* (x != (double) (int) x) is a hack to let small integers print nicely */
+
+ while (x < D_SCALE && x != (double) (int) x)
+ {
+ x *= 10.0;
+ nden++;
+ }
+
+ sprintf (line->p, "%.0f%n", x, &k);
+ line->p += k;
+ line->total += k;
+
+ for (i = 0; i < nnum; i++)
+ {
+ sprintf (line->p, "0");
+ line->p++;
+ line->total++;
+ }
+
+ if (nden)
+ {
+ sprintf (line->p, "/1%n", &k);
+ line->p += k;
+ line->total += k;
+ for (i = 0; i < nden; i++)
+ {
+ sprintf (line->p, "0");
+ line->p++;
+ line->total++;
+ }
+ }
+}
+#endif
+
+void EGLPNUM_TYPENAME_ILLwrite_lp_state_save_start (
+ EGLPNUM_TYPENAME_ILLwrite_lp_state * line)
+{
+ line->startlen = line->total;
+}
+
+void EGLPNUM_TYPENAME_ILLwrite_lp_state_start (
+ EGLPNUM_TYPENAME_ILLwrite_lp_state * line)
+{
+ int j;
+
+ for (j = 0; j < line->startlen; j++)
+ {
+ line->buf[j] = ' ';
+ }
+ line->buf[j] = '\0';
+ line->p = line->buf + j;
+ line->total = j;
+}
diff --git a/qsopt_ex/write_lp.h b/qsopt_ex/write_lp.h
new file mode 100644
index 0000000..6df6385
--- /dev/null
+++ b/qsopt_ex/write_lp.h
@@ -0,0 +1,73 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: wr_lp.h,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:57:39 $"; */
+#ifndef EGLPNUM_TYPENAME_WRITE_LP_STATE_H
+#define EGLPNUM_TYPENAME_WRITE_LP_STATE_H
+
+#include "eg_lpnum.h"
+#include "symtab.h"
+
+/****************************************************************************/
+/* */
+/* Routines to support writing of LP files */
+/* */
+/****************************************************************************/
+
+/*
+ * -) anything after '\' is comment
+ * -) variables consist of a-z A-Z 0-9!"#$%(),;.?@_`'{}|~
+ * don't start with a digit or '.'
+ */
+
+typedef struct EGLPNUM_TYPENAME_ILLwrite_lp_state
+{
+ char buf[ILL_namebufsize];
+ char *p;
+ int startlen;
+ int total;
+}
+EGLPNUM_TYPENAME_ILLwrite_lp_state;
+
+extern void EGLPNUM_TYPENAME_ILLwrite_lp_state_init (
+ EGLPNUM_TYPENAME_ILLwrite_lp_state * line,
+ const char *str);
+extern void EGLPNUM_TYPENAME_ILLwrite_lp_state_append (
+ EGLPNUM_TYPENAME_ILLwrite_lp_state * line,
+ const char *str);
+extern void EGLPNUM_TYPENAME_ILLwrite_lp_state_append_coef (
+ EGLPNUM_TYPENAME_ILLwrite_lp_state * line,
+ EGLPNUM_TYPE v,
+ int cnt);
+
+ /* append number sign ('+', '-') iff cnt > 0 or v < 0.0
+ * append number iff v != 1.0, v != -1.0
+ */
+extern void EGLPNUM_TYPENAME_ILLwrite_lp_state_append_number (
+ EGLPNUM_TYPENAME_ILLwrite_lp_state * line,
+ EGLPNUM_TYPE v);
+extern void EGLPNUM_TYPENAME_ILLwrite_lp_state_save_start (
+ EGLPNUM_TYPENAME_ILLwrite_lp_state * line);
+extern void EGLPNUM_TYPENAME_ILLwrite_lp_state_start (
+ EGLPNUM_TYPENAME_ILLwrite_lp_state * line);
+
+#endif
diff --git a/qsopt_ex/zeit.c b/qsopt_ex/zeit.c
new file mode 100644
index 0000000..bd4b7fc
--- /dev/null
+++ b/qsopt_ex/zeit.c
@@ -0,0 +1,292 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCSINFO $Id: zeit.c,v 1.2 2003/11/05 16:47:22 meven Exp $ */
+/****************************************************************************/
+/* */
+/* This file is part of CONCORDE */
+/* */
+/* (c) Copyright 1995--1999 by David Applegate, Robert Bixby, */
+/* Vasek Chvatal, and William Cook */
+/* */
+/* Permission is granted for academic research use. For other uses, */
+/* contact the authors for licensing options. */
+/* */
+/* Use at your own risk. We make no guarantees about the */
+/* correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/****************************************************************************/
+/* */
+/* TIMING FUNCTIONS */
+/* */
+/* TSP CODE */
+/* */
+/* */
+/* Written by: Applegate, Bixby, Chvatal, and Cook */
+/* Date: Summer 1994 (cofeb16) */
+/* December 1997 (dla) */
+/* */
+/* */
+/* EXPORTED FUNCTIONS: */
+/* */
+/* double ILLutil_zeit (void) */
+/* - To measure cpu time. */
+/* To use this, set double t = ILLutil_zeit (), run the function you */
+/* want to time, then compute ILLutil_zeit () - t. */
+/* */
+/* double ILLutil_real_zeit (void) */
+/* - To measure wall clock time. */
+/* */
+/* To use this, set double t = ILLutil_real_zeit (), run the function */
+/* you want to time, then compute ILLutil_real_zeit () - t. */
+/* */
+/* void ILLutil_init_timer (ILLutil_timer *t, const char *name) */
+/* - Initializes a ILLutil_timer, and gives it a name. */
+/* - The name is silently truncated if it is too long. */
+/* */
+/* void ILLutil_start_timer (ILLutil_timer *t) */
+/* - Starts the timer. */
+/* */
+/* void ILLutil_suspend_timer (ILLutil_timer *t) */
+/* - Suspends the timer. Similar to ILLutil_stop_timer, but doesn't */
+/* count a call, and doesn't output. */
+/* */
+/* void ILLutil_resume_timer (QSutil_timer *t) */
+/* - Resumes the timer after a suspend. */
+/* */
+/* double ILLutil_stop_timer (ILLutil_timer *t, int printit) */
+/* - Stops the timer, and returns the time since the last start. */
+/* - if printit == 1, outputs the time spent. */
+/* - if printit == 2, outputs the time spent only if nonzero */
+/* - if printit == 3,4, like 1,2, except brief, table-form output */
+/* */
+/* double ILLutil_total_timer (ILLutil_timer *t, int printit) */
+/* - Returns the cumulative time for this timer. */
+/* - if printit == 1, outputs the cumulative time. */
+/* - if printit == 2, outputs the cumulative time only if nonzero */
+/* - if printit == 3,4, like 1,2, except brief, table-form output */
+/* */
+/****************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include "logging-private.h"
+
+#include "util.h"
+
+#ifdef HAVE_GETRUSAGE
+
+#ifdef HAVE_SYS_RESOURCE_H
+# include <sys/resource.h>
+#endif
+
+#define ZEIT_FCT "getrusage"
+
+double ILLutil_zeit (
+ void)
+{
+ struct rusage ru;
+ double t;
+
+ getrusage (RUSAGE_SELF, &ru);
+
+ t = ((double) ru.ru_utime.tv_sec) +
+ ((double) ru.ru_utime.tv_usec) / 1000000.0;
+ return t;
+}
+#else /* HAVE_GETRUSAGE */
+
+#ifdef HAVE_TIMES
+
+#ifdef HAVE_SYS_PARAM_H
+# include <sys/param.h>
+#endif
+#ifdef HAVE_SYS_TIMES_H
+# include <sys/times.h>
+#endif
+
+#ifdef CLK_TCK
+#define MACHINE_FREQ CLK_TCK
+#else
+#define MACHINE_FREQ HZ
+#endif
+
+#define ZEIT_FCT "times"
+
+double ILLutil_zeit (
+ void)
+{
+ struct tms now;
+
+ times (&now);
+ return ((double) now.tms_utime) / ((double) MACHINE_FREQ);
+}
+#else /* HAVE_TIMES */
+
+#ifdef HAVE_CLOCK
+
+#ifndef CLOCKS_PER_SEC
+#ifdef CLK_TCK
+#define CLOCKS_PER_SEC CLK_TCK
+#else
+#define CLOCKS_PER_SEC 60
+#endif
+#endif
+
+#define ZEIT_FCT "clock"
+
+double ILLutil_zeit (
+ void)
+{
+ return ((double) clock ()) / ((double) CLOCKS_PER_SEC);
+}
+
+#else /* HAVE_CLOCK */
+
+#define ZEIT_FCT "???"
+
+double ILLutil_zeit (
+ void)
+{
+ return 0.0;
+}
+#endif /* HAVE_CLOCK */
+#endif /* HAVE_TIMES */
+#endif /* HAVE_GETRUSAGE */
+
+double ILLutil_real_zeit (
+ void)
+{
+ return time (0);
+}
+
+void ILLutil_init_timer (
+ ILLutil_timer * t,
+ const char *name)
+{
+ t->szeit = -1.0;
+ t->cum_zeit = 0.0;
+ t->count = 0;
+ if (name == (char *) NULL || name[0] == '\0')
+ {
+ strncpy (t->name, "ANONYMOUS", sizeof (t->name) - 1);
+ }
+ else
+ {
+ strncpy (t->name, name, sizeof (t->name) - 1);
+ }
+ t->name[sizeof (t->name) - 1] = '\0';
+}
+
+void ILLutil_start_timer (
+ ILLutil_timer * t)
+{
+ if (t->szeit != -1.0)
+ {
+ QSlog("Warning: restarting running timer %s", t->name);
+ }
+ t->szeit = ILLutil_zeit ();
+}
+
+void ILLutil_suspend_timer (
+ ILLutil_timer * t)
+{
+ if (t->szeit == -1.0)
+ {
+ QSlog("Warning: suspended non-running timer %s", t->name);
+ return;
+ }
+
+ t->cum_zeit += ILLutil_zeit () - t->szeit;
+ t->szeit = -1.0;
+}
+
+void ILLutil_resume_timer (
+ ILLutil_timer * t)
+{
+ if (t->szeit != -1.0)
+ {
+ QSlog("Warning: resuming running timer %s", t->name);
+ return;
+ }
+ t->szeit = ILLutil_zeit ();
+}
+
+static void ILL_print (
+ ILLutil_timer * t,
+ double z,
+ int printit)
+{
+ if (printit == 1 || (printit == 2 && z > 0.0))
+ {
+ if (t->count > 1)
+ {
+ QSlog("Time for %s: %.2f seconds (%.2f total in %d calls).",
+ t->name, z, t->cum_zeit, t->count);
+ }
+ else
+ {
+ QSlog("Time for %s: %.2f seconds.", t->name, z);
+ }
+ }
+ else if (printit == 3 || (printit == 4 && z > 0.0))
+ {
+ QSlog("T %-34.34s %9.2f %9.2f %d (%s)",
+ t->name, z, t->cum_zeit, t->count, ZEIT_FCT);
+ }
+}
+
+double ILLutil_stop_timer (
+ ILLutil_timer * t,
+ int printit)
+{
+ double z;
+
+ if (t->szeit == -1.0)
+ {
+ QSlog("Warning: stopping non-running timer %s", t->name);
+ return 0.0;
+ }
+ z = ILLutil_zeit () - t->szeit;
+ t->szeit = -1.0;
+ t->cum_zeit += z;
+ t->count++;
+ ILL_print (t, z, printit);
+ return z;
+}
+
+double ILLutil_total_timer (
+ ILLutil_timer * t,
+ int printit)
+{
+ double z = t->cum_zeit;
+
+ if (t->szeit != -1.0)
+ z += ILLutil_zeit () - t->szeit;
+ ILL_print (t, z, printit);
+ return z;
+}
diff --git a/qsopt_ex/zeit.h b/qsopt_ex/zeit.h
new file mode 100644
index 0000000..9793a1d
--- /dev/null
+++ b/qsopt_ex/zeit.h
@@ -0,0 +1,65 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+#ifndef __ZEIT_H__
+#define __ZEIT_H__
+/****************************************************************************/
+/* */
+/* zeit.c */
+/* */
+/****************************************************************************/
+
+typedef struct ILLutil_timer
+{
+ double szeit;
+ double cum_zeit;
+ char name[40];
+ int count;
+}
+ILLutil_timer;
+
+
+double ILLutil_zeit (
+ void),
+ ILLutil_real_zeit (
+ void),
+ ILLutil_stop_timer (
+ ILLutil_timer * t,
+ int printit),
+ ILLutil_total_timer (
+ ILLutil_timer * t,
+ int printit);
+
+
+void ILLutil_init_timer (
+ ILLutil_timer * t,
+ const char *name),
+ ILLutil_start_timer (
+ ILLutil_timer * t),
+ ILLutil_suspend_timer (
+ ILLutil_timer * t),
+ ILLutil_resume_timer (
+ ILLutil_timer * t);
+
+
+
+#endif
diff --git a/tap-driver.sh b/tap-driver.sh
new file mode 100755
index 0000000..4254e2b
--- /dev/null
+++ b/tap-driver.sh
@@ -0,0 +1,651 @@
+#! /bin/sh
+# Copyright (C) 2011-2014 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.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake at gnu.org> or send patches to
+# <automake-patches at gnu.org>.
+
+scriptversion=2013-12-23.17; # UTC
+
+# Make unconditional expansion of undefined variables an error. This
+# helps a lot in preventing typo-related bugs.
+set -u
+
+me=tap-driver.sh
+
+fatal ()
+{
+ echo "$me: fatal: $*" >&2
+ exit 1
+}
+
+usage_error ()
+{
+ echo "$me: $*" >&2
+ print_usage >&2
+ exit 2
+}
+
+print_usage ()
+{
+ cat <<END
+Usage:
+ tap-driver.sh --test-name=NAME --log-file=PATH --trs-file=PATH
+ [--expect-failure={yes|no}] [--color-tests={yes|no}]
+ [--enable-hard-errors={yes|no}] [--ignore-exit]
+ [--diagnostic-string=STRING] [--merge|--no-merge]
+ [--comments|--no-comments] [--] TEST-COMMAND
+The '--test-name', '-log-file' and '--trs-file' options are mandatory.
+END
+}
+
+# TODO: better error handling in option parsing (in particular, ensure
+# TODO: $log_file, $trs_file and $test_name are defined).
+test_name= # Used for reporting.
+log_file= # Where to save the result and output of the test script.
+trs_file= # Where to save the metadata of the test run.
+expect_failure=0
+color_tests=0
+merge=0
+ignore_exit=0
+comments=0
+diag_string='#'
+while test $# -gt 0; do
+ case $1 in
+ --help) print_usage; exit $?;;
+ --version) echo "$me $scriptversion"; exit $?;;
+ --test-name) test_name=$2; shift;;
+ --log-file) log_file=$2; shift;;
+ --trs-file) trs_file=$2; shift;;
+ --color-tests) color_tests=$2; shift;;
+ --expect-failure) expect_failure=$2; shift;;
+ --enable-hard-errors) shift;; # No-op.
+ --merge) merge=1;;
+ --no-merge) merge=0;;
+ --ignore-exit) ignore_exit=1;;
+ --comments) comments=1;;
+ --no-comments) comments=0;;
+ --diagnostic-string) diag_string=$2; shift;;
+ --) shift; break;;
+ -*) usage_error "invalid option: '$1'";;
+ esac
+ shift
+done
+
+test $# -gt 0 || usage_error "missing test command"
+
+case $expect_failure in
+ yes) expect_failure=1;;
+ *) expect_failure=0;;
+esac
+
+if test $color_tests = yes; then
+ init_colors='
+ color_map["red"]="[0;31m" # Red.
+ color_map["grn"]="[0;32m" # Green.
+ color_map["lgn"]="[1;32m" # Light green.
+ color_map["blu"]="[1;34m" # Blue.
+ color_map["mgn"]="[0;35m" # Magenta.
+ color_map["std"]="[m" # No color.
+ color_for_result["ERROR"] = "mgn"
+ color_for_result["PASS"] = "grn"
+ color_for_result["XPASS"] = "red"
+ color_for_result["FAIL"] = "red"
+ color_for_result["XFAIL"] = "lgn"
+ color_for_result["SKIP"] = "blu"'
+else
+ init_colors=''
+fi
+
+# :; is there to work around a bug in bash 3.2 (and earlier) which
+# does not always set '$?' properly on redirection failure.
+# See the Autoconf manual for more details.
+:;{
+ (
+ # Ignore common signals (in this subshell only!), to avoid potential
+ # problems with Korn shells. Some Korn shells are known to propagate
+ # to themselves signals that have killed a child process they were
+ # waiting for; this is done at least for SIGINT (and usually only for
+ # it, in truth). Without the `trap' below, such a behaviour could
+ # cause a premature exit in the current subshell, e.g., in case the
+ # test command it runs gets terminated by a SIGINT. Thus, the awk
+ # script we are piping into would never seen the exit status it
+ # expects on its last input line (which is displayed below by the
+ # last `echo $?' statement), and would thus die reporting an internal
+ # error.
+ # For more information, see the Autoconf manual and the threads:
+ # <http://lists.gnu.org/archive/html/bug-autoconf/2011-09/msg00004.html>
+ # <http://mail.opensolaris.org/pipermail/ksh93-integration-discuss/2009-February/004121.html>
+ trap : 1 3 2 13 15
+ if test $merge -gt 0; then
+ exec 2>&1
+ else
+ exec 2>&3
+ fi
+ "$@"
+ echo $?
+ ) | LC_ALL=C ${AM_TAP_AWK-awk} \
+ -v me="$me" \
+ -v test_script_name="$test_name" \
+ -v log_file="$log_file" \
+ -v trs_file="$trs_file" \
+ -v expect_failure="$expect_failure" \
+ -v merge="$merge" \
+ -v ignore_exit="$ignore_exit" \
+ -v comments="$comments" \
+ -v diag_string="$diag_string" \
+'
+# TODO: the usages of "cat >&3" below could be optimized when using
+# GNU awk, and/on on systems that supports /dev/fd/.
+
+# Implementation note: in what follows, `result_obj` will be an
+# associative array that (partly) simulates a TAP result object
+# from the `TAP::Parser` perl module.
+
+## ----------- ##
+## FUNCTIONS ##
+## ----------- ##
+
+function fatal(msg)
+{
+ print me ": " msg | "cat >&2"
+ exit 1
+}
+
+function abort(where)
+{
+ fatal("internal error " where)
+}
+
+# Convert a boolean to a "yes"/"no" string.
+function yn(bool)
+{
+ return bool ? "yes" : "no";
+}
+
+function add_test_result(result)
+{
+ if (!test_results_index)
+ test_results_index = 0
+ test_results_list[test_results_index] = result
+ test_results_index += 1
+ test_results_seen[result] = 1;
+}
+
+# Whether the test script should be re-run by "make recheck".
+function must_recheck()
+{
+ for (k in test_results_seen)
+ if (k != "XFAIL" && k != "PASS" && k != "SKIP")
+ return 1
+ return 0
+}
+
+# Whether the content of the log file associated to this test should
+# be copied into the "global" test-suite.log.
+function copy_in_global_log()
+{
+ for (k in test_results_seen)
+ if (k != "PASS")
+ return 1
+ return 0
+}
+
+function get_global_test_result()
+{
+ if ("ERROR" in test_results_seen)
+ return "ERROR"
+ if ("FAIL" in test_results_seen || "XPASS" in test_results_seen)
+ return "FAIL"
+ all_skipped = 1
+ for (k in test_results_seen)
+ if (k != "SKIP")
+ all_skipped = 0
+ if (all_skipped)
+ return "SKIP"
+ return "PASS";
+}
+
+function stringify_result_obj(result_obj)
+{
+ if (result_obj["is_unplanned"] || result_obj["number"] != testno)
+ return "ERROR"
+
+ if (plan_seen == LATE_PLAN)
+ return "ERROR"
+
+ if (result_obj["directive"] == "TODO")
+ return result_obj["is_ok"] ? "XPASS" : "XFAIL"
+
+ if (result_obj["directive"] == "SKIP")
+ return result_obj["is_ok"] ? "SKIP" : COOKED_FAIL;
+
+ if (length(result_obj["directive"]))
+ abort("in function stringify_result_obj()")
+
+ return result_obj["is_ok"] ? COOKED_PASS : COOKED_FAIL
+}
+
+function decorate_result(result)
+{
+ color_name = color_for_result[result]
+ if (color_name)
+ return color_map[color_name] "" result "" color_map["std"]
+ # If we are not using colorized output, or if we do not know how
+ # to colorize the given result, we should return it unchanged.
+ return result
+}
+
+function report(result, details)
+{
+ if (result ~ /^(X?(PASS|FAIL)|SKIP|ERROR)/)
+ {
+ msg = ": " test_script_name
+ add_test_result(result)
+ }
+ else if (result == "#")
+ {
+ msg = " " test_script_name ":"
+ }
+ else
+ {
+ abort("in function report()")
+ }
+ if (length(details))
+ msg = msg " " details
+ # Output on console might be colorized.
+ print decorate_result(result) msg
+ # Log the result in the log file too, to help debugging (this is
+ # especially true when said result is a TAP error or "Bail out!").
+ print result msg | "cat >&3";
+}
+
+function testsuite_error(error_message)
+{
+ report("ERROR", "- " error_message)
+}
+
+function handle_tap_result()
+{
+ details = result_obj["number"];
+ if (length(result_obj["description"]))
+ details = details " " result_obj["description"]
+
+ if (plan_seen == LATE_PLAN)
+ {
+ details = details " # AFTER LATE PLAN";
+ }
+ else if (result_obj["is_unplanned"])
+ {
+ details = details " # UNPLANNED";
+ }
+ else if (result_obj["number"] != testno)
+ {
+ details = sprintf("%s # OUT-OF-ORDER (expecting %d)",
+ details, testno);
+ }
+ else if (result_obj["directive"])
+ {
+ details = details " # " result_obj["directive"];
+ if (length(result_obj["explanation"]))
+ details = details " " result_obj["explanation"]
+ }
+
+ report(stringify_result_obj(result_obj), details)
+}
+
+# `skip_reason` should be empty whenever planned > 0.
+function handle_tap_plan(planned, skip_reason)
+{
+ planned += 0 # Avoid getting confused if, say, `planned` is "00"
+ if (length(skip_reason) && planned > 0)
+ abort("in function handle_tap_plan()")
+ if (plan_seen)
+ {
+ # Error, only one plan per stream is acceptable.
+ testsuite_error("multiple test plans")
+ return;
+ }
+ planned_tests = planned
+ # The TAP plan can come before or after *all* the TAP results; we speak
+ # respectively of an "early" or a "late" plan. If we see the plan line
+ # after at least one TAP result has been seen, assume we have a late
+ # plan; in this case, any further test result seen after the plan will
+ # be flagged as an error.
+ plan_seen = (testno >= 1 ? LATE_PLAN : EARLY_PLAN)
+ # If testno > 0, we have an error ("too many tests run") that will be
+ # automatically dealt with later, so do not worry about it here. If
+ # $plan_seen is true, we have an error due to a repeated plan, and that
+ # has already been dealt with above. Otherwise, we have a valid "plan
+ # with SKIP" specification, and should report it as a particular kind
+ # of SKIP result.
+ if (planned == 0 && testno == 0)
+ {
+ if (length(skip_reason))
+ skip_reason = "- " skip_reason;
+ report("SKIP", skip_reason);
+ }
+}
+
+function extract_tap_comment(line)
+{
+ if (index(line, diag_string) == 1)
+ {
+ # Strip leading `diag_string` from `line`.
+ line = substr(line, length(diag_string) + 1)
+ # And strip any leading and trailing whitespace left.
+ sub("^[ \t]*", "", line)
+ sub("[ \t]*$", "", line)
+ # Return what is left (if any).
+ return line;
+ }
+ return "";
+}
+
+# When this function is called, we know that line is a TAP result line,
+# so that it matches the (perl) RE "^(not )?ok\b".
+function setup_result_obj(line)
+{
+ # Get the result, and remove it from the line.
+ result_obj["is_ok"] = (substr(line, 1, 2) == "ok" ? 1 : 0)
+ sub("^(not )?ok[ \t]*", "", line)
+
+ # If the result has an explicit number, get it and strip it; otherwise,
+ # automatically assing the next progresive number to it.
+ if (line ~ /^[0-9]+$/ || line ~ /^[0-9]+[^a-zA-Z0-9_]/)
+ {
+ match(line, "^[0-9]+")
+ # The final `+ 0` is to normalize numbers with leading zeros.
+ result_obj["number"] = substr(line, 1, RLENGTH) + 0
+ line = substr(line, RLENGTH + 1)
+ }
+ else
+ {
+ result_obj["number"] = testno
+ }
+
+ if (plan_seen == LATE_PLAN)
+ # No further test results are acceptable after a "late" TAP plan
+ # has been seen.
+ result_obj["is_unplanned"] = 1
+ else if (plan_seen && testno > planned_tests)
+ result_obj["is_unplanned"] = 1
+ else
+ result_obj["is_unplanned"] = 0
+
+ # Strip trailing and leading whitespace.
+ sub("^[ \t]*", "", line)
+ sub("[ \t]*$", "", line)
+
+ # This will have to be corrected if we have a "TODO"/"SKIP" directive.
+ result_obj["description"] = line
+ result_obj["directive"] = ""
+ result_obj["explanation"] = ""
+
+ if (index(line, "#") == 0)
+ return # No possible directive, nothing more to do.
+
+ # Directives are case-insensitive.
+ rx = "[ \t]*#[ \t]*([tT][oO][dD][oO]|[sS][kK][iI][pP])[ \t]*"
+
+ # See whether we have the directive, and if yes, where.
+ pos = match(line, rx "$")
+ if (!pos)
+ pos = match(line, rx "[^a-zA-Z0-9_]")
+
+ # If there was no TAP directive, we have nothing more to do.
+ if (!pos)
+ return
+
+ # Let`s now see if the TAP directive has been escaped. For example:
+ # escaped: ok \# SKIP
+ # not escaped: ok \\# SKIP
+ # escaped: ok \\\\\# SKIP
+ # not escaped: ok \ # SKIP
+ if (substr(line, pos, 1) == "#")
+ {
+ bslash_count = 0
+ for (i = pos; i > 1 && substr(line, i - 1, 1) == "\\"; i--)
+ bslash_count += 1
+ if (bslash_count % 2)
+ return # Directive was escaped.
+ }
+
+ # Strip the directive and its explanation (if any) from the test
+ # description.
+ result_obj["description"] = substr(line, 1, pos - 1)
+ # Now remove the test description from the line, that has been dealt
+ # with already.
+ line = substr(line, pos)
+ # Strip the directive, and save its value (normalized to upper case).
+ sub("^[ \t]*#[ \t]*", "", line)
+ result_obj["directive"] = toupper(substr(line, 1, 4))
+ line = substr(line, 5)
+ # Now get the explanation for the directive (if any), with leading
+ # and trailing whitespace removed.
+ sub("^[ \t]*", "", line)
+ sub("[ \t]*$", "", line)
+ result_obj["explanation"] = line
+}
+
+function get_test_exit_message(status)
+{
+ if (status == 0)
+ return ""
+ if (status !~ /^[1-9][0-9]*$/)
+ abort("getting exit status")
+ if (status < 127)
+ exit_details = ""
+ else if (status == 127)
+ exit_details = " (command not found?)"
+ else if (status >= 128 && status <= 255)
+ exit_details = sprintf(" (terminated by signal %d?)", status - 128)
+ else if (status > 256 && status <= 384)
+ # We used to report an "abnormal termination" here, but some Korn
+ # shells, when a child process die due to signal number n, can leave
+ # in $? an exit status of 256+n instead of the more standard 128+n.
+ # Apparently, both behaviours are allowed by POSIX (2008), so be
+ # prepared to handle them both. See also Austing Group report ID
+ # 0000051 <http://www.austingroupbugs.net/view.php?id=51>
+ exit_details = sprintf(" (terminated by signal %d?)", status - 256)
+ else
+ # Never seen in practice.
+ exit_details = " (abnormal termination)"
+ return sprintf("exited with status %d%s", status, exit_details)
+}
+
+function write_test_results()
+{
+ print ":global-test-result: " get_global_test_result() > trs_file
+ print ":recheck: " yn(must_recheck()) > trs_file
+ print ":copy-in-global-log: " yn(copy_in_global_log()) > trs_file
+ for (i = 0; i < test_results_index; i += 1)
+ print ":test-result: " test_results_list[i] > trs_file
+ close(trs_file);
+}
+
+BEGIN {
+
+## ------- ##
+## SETUP ##
+## ------- ##
+
+'"$init_colors"'
+
+# Properly initialized once the TAP plan is seen.
+planned_tests = 0
+
+COOKED_PASS = expect_failure ? "XPASS": "PASS";
+COOKED_FAIL = expect_failure ? "XFAIL": "FAIL";
+
+# Enumeration-like constants to remember which kind of plan (if any)
+# has been seen. It is important that NO_PLAN evaluates "false" as
+# a boolean.
+NO_PLAN = 0
+EARLY_PLAN = 1
+LATE_PLAN = 2
+
+testno = 0 # Number of test results seen so far.
+bailed_out = 0 # Whether a "Bail out!" directive has been seen.
+
+# Whether the TAP plan has been seen or not, and if yes, which kind
+# it is ("early" is seen before any test result, "late" otherwise).
+plan_seen = NO_PLAN
+
+## --------- ##
+## PARSING ##
+## --------- ##
+
+is_first_read = 1
+
+while (1)
+ {
+ # Involutions required so that we are able to read the exit status
+ # from the last input line.
+ st = getline
+ if (st < 0) # I/O error.
+ fatal("I/O error while reading from input stream")
+ else if (st == 0) # End-of-input
+ {
+ if (is_first_read)
+ abort("in input loop: only one input line")
+ break
+ }
+ if (is_first_read)
+ {
+ is_first_read = 0
+ nextline = $0
+ continue
+ }
+ else
+ {
+ curline = nextline
+ nextline = $0
+ $0 = curline
+ }
+ # Copy any input line verbatim into the log file.
+ print | "cat >&3"
+ # Parsing of TAP input should stop after a "Bail out!" directive.
+ if (bailed_out)
+ continue
+
+ # TAP test result.
+ if ($0 ~ /^(not )?ok$/ || $0 ~ /^(not )?ok[^a-zA-Z0-9_]/)
+ {
+ testno += 1
+ setup_result_obj($0)
+ handle_tap_result()
+ }
+ # TAP plan (normal or "SKIP" without explanation).
+ else if ($0 ~ /^1\.\.[0-9]+[ \t]*$/)
+ {
+ # The next two lines will put the number of planned tests in $0.
+ sub("^1\\.\\.", "")
+ sub("[^0-9]*$", "")
+ handle_tap_plan($0, "")
+ continue
+ }
+ # TAP "SKIP" plan, with an explanation.
+ else if ($0 ~ /^1\.\.0+[ \t]*#/)
+ {
+ # The next lines will put the skip explanation in $0, stripping
+ # any leading and trailing whitespace. This is a little more
+ # tricky in truth, since we want to also strip a potential leading
+ # "SKIP" string from the message.
+ sub("^[^#]*#[ \t]*(SKIP[: \t][ \t]*)?", "")
+ sub("[ \t]*$", "");
+ handle_tap_plan(0, $0)
+ }
+ # "Bail out!" magic.
+ # Older versions of prove and TAP::Harness (e.g., 3.17) did not
+ # recognize a "Bail out!" directive when preceded by leading
+ # whitespace, but more modern versions (e.g., 3.23) do. So we
+ # emulate the latter, "more modern" behaviour.
+ else if ($0 ~ /^[ \t]*Bail out!/)
+ {
+ bailed_out = 1
+ # Get the bailout message (if any), with leading and trailing
+ # whitespace stripped. The message remains stored in `$0`.
+ sub("^[ \t]*Bail out![ \t]*", "");
+ sub("[ \t]*$", "");
+ # Format the error message for the
+ bailout_message = "Bail out!"
+ if (length($0))
+ bailout_message = bailout_message " " $0
+ testsuite_error(bailout_message)
+ }
+ # Maybe we have too look for dianogtic comments too.
+ else if (comments != 0)
+ {
+ comment = extract_tap_comment($0);
+ if (length(comment))
+ report("#", comment);
+ }
+ }
+
+## -------- ##
+## FINISH ##
+## -------- ##
+
+# A "Bail out!" directive should cause us to ignore any following TAP
+# error, as well as a non-zero exit status from the TAP producer.
+if (!bailed_out)
+ {
+ if (!plan_seen)
+ {
+ testsuite_error("missing test plan")
+ }
+ else if (planned_tests != testno)
+ {
+ bad_amount = testno > planned_tests ? "many" : "few"
+ testsuite_error(sprintf("too %s tests run (expected %d, got %d)",
+ bad_amount, planned_tests, testno))
+ }
+ if (!ignore_exit)
+ {
+ # Fetch exit status from the last line.
+ exit_message = get_test_exit_message(nextline)
+ if (exit_message)
+ testsuite_error(exit_message)
+ }
+ }
+
+write_test_results()
+
+exit 0
+
+} # End of "BEGIN" block.
+'
+
+# TODO: document that we consume the file descriptor 3 :-(
+} 3>"$log_file"
+
+test $? -eq 0 || fatal "I/O or internal error"
+
+# 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/tests/eg_lpnum_ex.c b/tests/eg_lpnum_ex.c
new file mode 100644
index 0000000..e7a4653
--- /dev/null
+++ b/tests/eg_lpnum_ex.c
@@ -0,0 +1,297 @@
+/* EGlib "Efficient General Library" provides some basic structures and
+ * algorithms commons in many optimization algorithms.
+ *
+ * Copyright (C) 2005 Daniel Espinoza and Marcos Goycoolea.
+ *
+ * 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
+ * */
+/** @file
+ * @ingroup EGlpNum
+ * */
+/** @addtogroup EGlpNum */
+/** @{ */
+#include "eg_lpnum.h"
+/* ========================================================================= */
+/** @brief Tester program for EGlpNum_t structure and functions
+ * @return zero on success, non-zero otherwise
+ * @par Description:
+ * Perform various tests on EGlpNum_t and their functions
+ * */
+int main (int argc,
+ char **argv)
+{
+ /* local variables */
+ EGlpNum_t ntmp[4];
+ double dtmp[5];
+ char *strnum1,
+ *strnum2,
+ *strnum3;
+ int rval=0;
+ #ifdef HAVE_LIBGMP
+ int n_char = 0;
+ mpq_t qnum;
+ #endif
+ EGlpNumStart();
+ /* set signal and limits */
+ EGsigSet(rval,CLEANUP);
+ EGsetLimits(3600.0,4294967295UL);
+ #ifdef HAVE_LIBGMP
+ EGlpNumSetPrecision (128);
+ mpq_init (qnum);
+ #endif
+ EGlpNumInitVar (ntmp[0]);
+ EGlpNumInitVar (ntmp[1]);
+ EGlpNumInitVar (ntmp[2]);
+ EGlpNumInitVar (ntmp[3]);
+ /* the input should have at least two parameters, namelly the number where we
+ * will work on */
+ if (argc < 3)
+ {
+ fprintf (stderr,
+ "usage: %s num1 num2\n\tWhere num1 and num2 are numbers in"
+ " the number format (either a/b or regular doubles)\n", argv[0]);
+ exit (1);
+ }
+
+ /* we ask for two numbers and perform some basic operations and compare
+ * aganist double arithmetic */
+ #ifdef HAVE_LIBGMP
+ n_char = mpq_EGlpNumReadStrXc (qnum, argv[1]);
+ #endif
+ EGlpNumReadStr (ntmp[0], argv[1]);
+ EGlpNumReadStr (ntmp[1], argv[2]);
+ dtmp[0] = EGlpNumToLf (ntmp[0]);
+ dtmp[1] = EGlpNumToLf (ntmp[1]);
+
+ /* convert numbers */
+ strnum1 = EGlpNumGetStr (ntmp[0]);
+ strnum2 = EGlpNumGetStr (ntmp[1]);
+ fprintf (stderr, "You Input %s (%lg) and %s (%lg)\n", strnum1, dtmp[0],
+ strnum2, dtmp[1]);
+ #ifdef HAVE_LIBGMP
+ strnum3 = mpq_EGlpNumGetStr (qnum);
+ fprintf (stderr, "Your first number represented as exact rational is %s, "
+ "readed with %d chars\n", strnum3, n_char);
+ free (strnum3);
+ mpq_EGlpNumSet (qnum, dtmp[0]);
+ strnum3 = mpq_EGlpNumGetStr (qnum);
+ fprintf (stderr, "Your first number represented as continuous fraction "
+ "is %s, readed with %d chars\n", strnum3, n_char);
+ free (strnum3);
+ #endif
+
+ /* internal constants */
+ strnum3 = EGlpNumGetStr (oneLpNum);
+ fprintf (stderr, "1.0 = %s\n", strnum3);
+ EGfree (strnum3);
+ strnum3 = EGlpNumGetStr (zeroLpNum);
+ fprintf (stderr, "0.0 = %s\n", strnum3);
+ EGfree (strnum3);
+ strnum3 = EGlpNumGetStr (epsLpNum);
+ fprintf (stderr, "eps = %s\n", strnum3);
+ EGfree (strnum3);
+ strnum3 = EGlpNumGetStr (MaxLpNum);
+ fprintf (stderr, "Max = %s\n", strnum3);
+ EGfree (strnum3);
+ strnum3 = EGlpNumGetStr (MinLpNum);
+ fprintf (stderr, "Min = %s\n", strnum3);
+ EGfree (strnum3);
+
+ /* copying functions */
+ EGlpNumCopy (ntmp[2], ntmp[0]);
+ strnum3 = EGlpNumGetStr (ntmp[2]);
+ fprintf (stderr, "%s = %s (%lg)\n", strnum3, strnum1, dtmp[0]);
+ EGfree (strnum3);
+ EGlpNumCopyDiff (ntmp[2], ntmp[0], ntmp[1]);
+ strnum3 = EGlpNumGetStr (ntmp[2]);
+ fprintf (stderr, "%s = %s - %s (%lg)\n", strnum3, strnum1, strnum2,
+ dtmp[0] - dtmp[1]);
+ EGfree (strnum3);
+ EGlpNumCopyDiffRatio (ntmp[2], ntmp[0], ntmp[1], ntmp[0]);
+ strnum3 = EGlpNumGetStr (ntmp[2]);
+ fprintf (stderr, "%s = (%s - %s)/%s (%lg)\n", strnum3, strnum1, strnum2,
+ strnum1, (dtmp[0] - dtmp[1]) / dtmp[0]);
+ EGfree (strnum3);
+ EGlpNumCopySum (ntmp[2], ntmp[0], ntmp[1]);
+ strnum3 = EGlpNumGetStr (ntmp[2]);
+ fprintf (stderr, "%s = %s + %s (%lg)\n", strnum3, strnum1, strnum2,
+ dtmp[0] + dtmp[1]);
+ EGfree (strnum3);
+ EGlpNumCopySqrOver (ntmp[2], ntmp[1], ntmp[0]);
+ strnum3 = EGlpNumGetStr (ntmp[2]);
+ fprintf (stderr, "%s = %s^2/%s (%lg)\n", strnum3, strnum2, strnum1,
+ dtmp[1] * dtmp[1] / dtmp[0]);
+ EGfree (strnum3);
+ EGlpNumCopyAbs (ntmp[2], ntmp[0]);
+ strnum3 = EGlpNumGetStr (ntmp[2]);
+ fprintf (stderr, "%s = |%s| (%lg)\n", strnum3, strnum1, fabs (dtmp[0]));
+ EGfree (strnum3);
+ EGlpNumCopyNeg (ntmp[2], ntmp[0]);
+ strnum3 = EGlpNumGetStr (ntmp[2]);
+ fprintf (stderr, "%s = -1*%s (%lg)\n", strnum3, strnum1, -dtmp[0]);
+ EGfree (strnum3);
+ EGlpNumCopyFrac (ntmp[2], ntmp[1], ntmp[0]);
+ strnum3 = EGlpNumGetStr (ntmp[2]);
+ fprintf (stderr, "%s = %s/%s (%lg)\n", strnum3, strnum2, strnum1,
+ dtmp[1] / dtmp[0]);
+ EGfree (strnum3);
+
+ /* add */
+ EGlpNumCopy (ntmp[2], ntmp[0]);
+ EGlpNumAddTo (ntmp[2], ntmp[1]);
+ strnum3 = EGlpNumGetStr (ntmp[2]);
+ fprintf (stderr, "%s + %s = %s (%lg)\n", strnum1, strnum2, strnum3,
+ dtmp[0] + dtmp[1]);
+ EGfree (strnum3);
+ EGlpNumCopy (ntmp[2], ntmp[0]);
+ EGlpNumAddUiTo (ntmp[2], 0xffU);
+ strnum3 = EGlpNumGetStr (ntmp[2]);
+ fprintf (stderr, "%s + %u = %s (%lg)\n", strnum1, 0xffU, strnum3,
+ dtmp[0] + 0xffU);
+ EGfree (strnum3);
+
+ /* substract */
+ EGlpNumCopy (ntmp[2], ntmp[0]);
+ EGlpNumSubTo (ntmp[2], ntmp[1]);
+ strnum3 = EGlpNumGetStr (ntmp[2]);
+ fprintf (stderr, "%s - %s = %s (%lg)\n", strnum1, strnum2, strnum3,
+ dtmp[0] - dtmp[1]);
+ EGfree (strnum3);
+ EGlpNumCopy (ntmp[2], ntmp[0]);
+ EGlpNumSubUiTo (ntmp[2], 0xffU);
+ strnum3 = EGlpNumGetStr (ntmp[2]);
+ fprintf (stderr, "%s - %u = %s (%lg)\n", strnum1, 0xffU, strnum3,
+ dtmp[0] - 0xffU);
+ EGfree (strnum3);
+
+ /* multiply */
+ EGlpNumCopy (ntmp[2], ntmp[0]);
+ EGlpNumMultTo (ntmp[2], ntmp[1]);
+ strnum3 = EGlpNumGetStr (ntmp[2]);
+ fprintf (stderr, "%s * %s = %s (%lg)\n", strnum1, strnum2, strnum3,
+ dtmp[0] * dtmp[1]);
+ EGfree (strnum3);
+
+ /* multiply unsigned */
+ EGlpNumCopy (ntmp[2], ntmp[0]);
+ EGlpNumMultUiTo (ntmp[2], 13);
+ strnum3 = EGlpNumGetStr (ntmp[2]);
+ fprintf (stderr, "%s * 13 = %s (%lg)\n", strnum1, strnum3, dtmp[0] * 13);
+ EGfree (strnum3);
+
+ /* inverse */
+ EGlpNumCopy (ntmp[2], ntmp[0]);
+ EGlpNumInv (ntmp[2]);
+ strnum3 = EGlpNumGetStr (ntmp[2]);
+ fprintf (stderr, "1/%s = %s (%lg)\n", strnum1, strnum3, 1.0 / dtmp[0]);
+ EGfree (strnum3);
+
+ /* floor and ceil */
+ EGlpNumFloor (ntmp[2], ntmp[0]);
+ strnum3 = EGlpNumGetStr (ntmp[2]);
+ fprintf (stderr, "floor(%s) = %s (%lg)\n", strnum1, strnum3, floor (dtmp[0]));
+ EGfree (strnum3);
+ EGlpNumCeil (ntmp[2], ntmp[0]);
+ strnum3 = EGlpNumGetStr (ntmp[2]);
+ fprintf (stderr, "ceil(%s) = %s (%lg)\n", strnum1, strnum3, ceil (dtmp[0]));
+ EGfree (strnum3);
+
+ /* negative and inner products */
+ EGlpNumCopy (ntmp[2], ntmp[0]);
+ EGlpNumSign (ntmp[2]);
+ strnum3 = EGlpNumGetStr (ntmp[2]);
+ fprintf (stderr, "-(%s) = %s (%lg)\n", strnum1, strnum3, -dtmp[0]);
+ EGfree (strnum3);
+ EGlpNumOne (ntmp[2]);
+ EGlpNumAddInnProdTo (ntmp[2], ntmp[0], ntmp[1]);
+ strnum3 = EGlpNumGetStr (ntmp[2]);
+ fprintf (stderr, "1.0 + %s*%s = %s (%lg)\n", strnum1, strnum2, strnum3,
+ 1.0 + dtmp[1] * dtmp[0]);
+ EGfree (strnum3);
+ EGlpNumOne (ntmp[2]);
+ EGlpNumSubInnProdTo (ntmp[2], ntmp[0], ntmp[1]);
+ strnum3 = EGlpNumGetStr (ntmp[2]);
+ fprintf (stderr, "1.0 - %s*%s = %s (%lg)\n", strnum1, strnum2, strnum3,
+ 1.0 - dtmp[1] * dtmp[0]);
+ EGfree (strnum3);
+
+ /* divide */
+ EGlpNumCopy (ntmp[2], ntmp[0]);
+ EGlpNumDivTo (ntmp[2], ntmp[1]);
+ strnum3 = EGlpNumGetStr (ntmp[2]);
+ fprintf (stderr, "%s / %s = %s (%lg)\n", strnum1, strnum2, strnum3,
+ dtmp[0] / dtmp[1]);
+ EGfree (strnum3);
+ EGlpNumCopy (ntmp[2], ntmp[0]);
+ EGlpNumDivUiTo (ntmp[2], 0xffU);
+ strnum3 = EGlpNumGetStr (ntmp[2]);
+ fprintf (stderr, "%s / %u = %s (%lg)\n", strnum1, 0xffU, strnum3,
+ dtmp[0] / 0xffU);
+ EGfree (strnum3);
+ EGfree (strnum1);
+ EGfree (strnum2);
+
+#ifdef HAVE_LIBGMP
+ /* test transformation to rationals */
+ {
+ mpq_t n1, n2;
+ mpf_t f1, f2;
+ mpq_init (n1);
+ mpq_init (n2);
+ mpf_init (f1);
+ mpf_init (f2);
+ mpf_EGlpNumSet(f1,EGlpNumToLf(ntmp[0]));
+ mpf_EGlpNumSet(f2,EGlpNumToLf(ntmp[1]));
+ mpq_EGlpNumSet_mpf (n1, f1);
+ mpq_EGlpNumSet_mpf (n2, f2);
+ strnum1 = mpq_EGlpNumGetStr (n1);
+ strnum2 = mpq_EGlpNumGetStr (n2);
+ fprintf (stderr, "Your input in rational was:\n\t(%10.7lf) %s\n\t(%10.7lf)"
+ " %s\n", EGlpNumToLf (ntmp[0]), strnum1, EGlpNumToLf (ntmp[1]),
+ strnum2);
+ EGfree (strnum1);
+ EGfree (strnum2);
+
+ /* test natural exponentiation */
+ mpf_EGlpNumEpow (f1, -38.81624211135693732736499880);
+ mpf_set_ui (f2, (unsigned long)1);
+ mpf_div_2exp (f2, f2, (unsigned long)56);
+ strnum1 = mpf_EGlpNumGetStr (f1);
+ strnum2 = mpf_EGlpNumGetStr (f2);
+ fprintf (stderr, "2^-56 = %s ~ %s\n", strnum1, strnum2);
+ EGfree (strnum1);
+ EGfree (strnum2);
+ mpq_clear (n1);
+ mpq_clear (n2);
+ mpf_clear (f1);
+ mpf_clear (f2);
+ }
+#endif
+
+ /* ending */
+ CLEANUP:
+ EGlpNumClearVar (ntmp[0]);
+ EGlpNumClearVar (ntmp[1]);
+ EGlpNumClearVar (ntmp[2]);
+ EGlpNumClearVar (ntmp[3]);
+ #ifdef HAVE_LIBGMP
+ mpq_clear (qnum);
+ #endif
+ EGlpNumClear();
+ return 0;
+}
+
+/* ========================================================================= */
+/** @} */
diff --git a/tests/eg_sloan.c b/tests/eg_sloan.c
new file mode 100644
index 0000000..38e7833
--- /dev/null
+++ b/tests/eg_sloan.c
@@ -0,0 +1,243 @@
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "qs_config.h"
+#include "logging-private.h"
+
+#include "QSopt_ex.h"
+/* ========================================================================= */
+/** @name Static Variables
+ * Set of static variables for this program. */
+/*@{*/
+/** @brief range of values for first OA level */
+static unsigned s1 = 3;
+/** @brief range of values for second OA level */
+static unsigned s2 = 3;
+/** @brief number of columns for first OA level */
+static unsigned k1 = 3;
+/** @brief number of columns for second OA level */
+static unsigned k2 = 3;
+/** @brief use (or not) scaling of the resulting LP */
+static int use_scaling = 1;
+/** @brief use dlouble floating point output */
+static int use_double = 0;
+/** @brief file name output. */
+const char *out_file = "output.lp";
+/** @brief Strength level required */
+static unsigned t = 2;
+/** @brief temporal string space */
+char strtmp[1024];
+/*@}*/
+
+/* ========================================================================= */
+/** @brief Display options to the screen */
+static inline void sl_usage (char const *const s)
+{
+ fprintf (stderr,
+ "This programs compute bounds for mixed-level orthogonal arrays (OA) of different strengths for two levels\n");
+ fprintf (stderr, "Usage: %s [options]\n", s);
+ fprintf (stderr, " -a n range of values for the first OA level (>=2)\n");
+ fprintf (stderr,
+ " -b n range of values for the second OA level (>=2)\n");
+ fprintf (stderr,
+ " -c n number of columns for the first OA level (>=2)\n");
+ fprintf (stderr,
+ " -e n number of columns for the second OA level (>=2)\n");
+ fprintf (stderr,
+ " -d n if n > 0, write the LP in double precition arithmetic, otherwise, write it in rational form\n");
+ fprintf (stderr, " -o f filename where to write the output LP\n");
+ fprintf (stderr,
+ " -s n if n > 0 scale the resulting LP, otherwise present the unscaled LP\n");
+ fprintf (stderr, " -t n required strength of the OA (>=1)\n");
+}
+
+/* ========================================================================= */
+/** @brief Display options to the screen */
+static inline int sl_parseargs (int argc,
+ char **argv)
+{
+ int c;
+ while ((c = getopt (argc, argv, "a:b:c:e:s:d:o:t:")) != EOF)
+ {
+ switch (c)
+ {
+ case 'a':
+ s1 = atoi (optarg);
+ break;
+ case 'b':
+ s2 = atoi (optarg);
+ break;
+ case 'c':
+ k1 = atoi (optarg);
+ break;
+ case 'e':
+ k2 = atoi (optarg);
+ break;
+ case 's':
+ use_scaling = atoi (optarg);
+ break;
+ case 'd':
+ use_double = atoi (optarg);
+ break;
+ case 'o':
+ out_file = optarg;
+ break;
+ case 't':
+ t = atoi (optarg);
+ break;
+ default:
+ sl_usage (argv[0]);
+ return 1;
+ }
+ }
+ if (s1 < 2 || s2 < 2 || k1 < 1 || k2 < 1 || t < 1)
+ {
+ sl_usage (argv[0]);
+ return 1;
+ }
+ fprintf (stderr, "Running %s\nOptions:\n", argv[0]);
+ fprintf (stderr, "\tfirst level columns = %d\n", k1);
+ fprintf (stderr, "\tsecond level columns = %d\n", k2);
+ fprintf (stderr, "\tfirst level range = %d\n", s1);
+ fprintf (stderr, "\tsecond level range = %d\n", s2);
+ fprintf (stderr, "\tt = %d\n", t);
+ fprintf (stderr, "\t%s scaling\n", use_scaling ? "using" : "not using");
+ fprintf (stderr, "\t%s output\n", use_double ? "double" : "rational");
+ fprintf (stderr, "\toutput file : %s\n", out_file);
+ return 0;
+}
+
+/* ========================================================================= */
+/** @brief compute the krawtchouk ppolynomial, defined as
+ * \f[P^s_j(x,m)=\sum\limits_{i=0}^j(-1)^i(s-1)^{j-i}\binom{x}{i}\binom{m-x}{j-i}\f]
+ * @param x the \f$x\f$ parameter of the function.
+ * @param s the \f$s\f$ parameter of the function.
+ * @param j the \f$j\f$ parameter of the function.
+ * @param m the \f$m\f$ parameter of the function.
+ * @param rop where to store the result */
+void Kpoly (unsigned x,
+ unsigned s,
+ unsigned j,
+ unsigned m,
+ mpz_t rop)
+{
+ register unsigned i = j + 1;
+ mpz_t z1,
+ z2;
+ mpz_init (z1);
+ mpz_init (z2);
+ mpz_set_ui (rop, (unsigned long)0);
+ EXIT (m < x, "m < x! impossible!");
+ EXIT (s < 1, "s < 1! impossible!");
+ while (i--)
+ {
+ mpz_bin_uiui (z1, (unsigned long)x, (unsigned long)i);
+ mpz_set (z2, z1);
+ mpz_bin_uiui (z1, (unsigned long)(m - x), (unsigned long)(j - i));
+ mpz_mul (z2, z2, z1);
+ mpz_ui_pow_ui (z1, (unsigned long)(s - 1), (unsigned long)(j - i));
+ mpz_mul (z2, z2, z1);
+ if (i & 1U)
+ mpz_sub (rop, rop, z2);
+ else
+ mpz_add (rop, rop, z2);
+ }
+ mpz_clear (z1);
+ mpz_clear (z2);
+}
+
+/* ========================================================================= */
+/** @brief main function, here we build the LP, execute the options and exit */
+int main (int argc,
+ char **argv)
+{
+ int rval = 0;
+ mpq_t v1,
+ v2;
+ mpq_QSdata *p_mpq = 0;
+ dbl_QSdata *p_dbl = 0;
+ register unsigned i,
+ j,
+ k,
+ l;
+ /* parse input */
+ QSopt_ex_version();
+ QSexactStart();
+ rval = sl_parseargs (argc, argv);
+ if (rval)
+ return rval;
+ mpq_init (v1);
+ mpq_init (v2);
+ /* create the problem with the appropriate number of variables and
+ * constraints */
+ snprintf (strtmp, (size_t)1023, "OA_SL_%d-%d_%d-%d_t-%d", s1, k1, s2, k2, t);
+ p_mpq = mpq_QScreate_prob (strtmp, QS_MIN);
+ for (i = 0; i <= k1; i++)
+ for (j = 0; j <= k2; j++)
+ {
+ snprintf (strtmp, (size_t)1023, "V_%d_%d", i, j);
+ rval =
+ mpq_QSnew_col (p_mpq, mpq_oneLpNum,
+ (i + j == 0) ? mpq_oneLpNum : mpq_zeroLpNum,
+ mpq_ILL_MAXDOUBLE, strtmp);
+ CHECKRVALG (rval, CLEANUP);
+ strtmp[0] = 'C';
+ rval = mpq_QSnew_row (p_mpq, mpq_zeroLpNum,
+ ((i + j >= 1) && (i + j <= t)) ? 'E' : 'G', strtmp);
+ CHECKRVALG (rval, CLEANUP);
+ }
+ /* now set the coefficients */
+ for (i = 0; i <= k1; i++)
+ for (j = 0; j <= k2; j++)
+ for (k = 0; k <= k1; k++)
+ for (l = 0; l <= k2; l++)
+ {
+ Kpoly (k, s1, i, k1, mpq_numref (v2));
+ Kpoly (l, s2, j, k2, mpq_numref (v1));
+ mpq_mul (v1, v1, v2);
+ if (mpz_cmp_ui (mpq_numref (v1), (unsigned long)0))
+ {
+ rval =
+ mpq_QSchange_coef (p_mpq, ((int)(j + i * (k2 + 1))), (int)(l + k * (k2 + 1)), v1);
+ CHECKRVALG (rval, CLEANUP);
+ }
+ }
+ /* now, if we are using scaling, we scale the non-zeros */
+ if (use_scaling)
+ {
+ mpq_set_ui (v1, (unsigned long)1, (unsigned long)1);
+ EXutilSimplify ((unsigned)(p_mpq->qslp->A.matsize), p_mpq->qslp->A.matval, v1);
+ mpq_div (v2, mpq_oneLpNum, v1);
+ fprintf (stderr, "Scale factor %lf\n", mpq_get_d (v2));
+ }
+ /* now we save the LP */
+ if (use_double)
+ {
+ snprintf (strtmp, (size_t)1023, "OA_SL_%d-%d_%d-%d_t-%d", s1, k1, s2, k2, t);
+ p_dbl = QScopy_prob_mpq_dbl (p_mpq, strtmp);
+ rval = dbl_QSwrite_prob (p_dbl, out_file, "LP");
+ CHECKRVALG (rval, CLEANUP);
+ }
+ else
+ {
+ rval = mpq_QSwrite_prob (p_mpq, out_file, "LP");
+ CHECKRVALG (rval, CLEANUP);
+ }
+
+ /* ending */
+CLEANUP:
+ if (p_mpq)
+ mpq_QSfree_prob (p_mpq);
+ if (p_dbl)
+ dbl_QSfree_prob (p_dbl);
+ mpq_clear (v1);
+ mpq_clear (v2);
+ QSexactClear();
+ return rval;
+}
diff --git a/tests/eg_sloan.h b/tests/eg_sloan.h
new file mode 100644
index 0000000..facf073
--- /dev/null
+++ b/tests/eg_sloan.h
@@ -0,0 +1,9 @@
+#ifndef __SLOAN_LP__
+#define __SLOAN_LP__
+#include <stdio.h>
+
+#if OS == LINUX
+#include <getopt.h>
+#endif
+#include "exact.h"
+#endif
diff --git a/tests/ftest.c b/tests/ftest.c
new file mode 100644
index 0000000..73865f5
--- /dev/null
+++ b/tests/ftest.c
@@ -0,0 +1,303 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: ftest.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+
+#include "qs_config.h"
+#include "config.h"
+#include "iqsutil.h"
+#include "lpdefs.h"
+#include "factor.h"
+
+#define NREP 2
+#define MAXITER 10000
+#undef DENSE_READ
+//static int TRACE = 0;
+
+#if 0
+static int handle_singularity (
+ void *sdata,
+ int c,
+ int r)
+{
+ fprintf (stderr, "singular basis, replace column %d by row %d logical\n",
+ r, c);
+ return 0;
+}
+#endif
+
+int main (
+ int ac,
+ char **av)
+{
+ factor_work f;
+ int dim = 0;
+ int ncol = 0;
+ int nzcnt = 0;
+ int *basis = (int *) NULL;
+ int *cbeg = (int *) NULL;
+ int *clen = (int *) NULL;
+ int *cind = (int *) NULL;
+ EGlpNum_t *coef = (EGlpNum_t *) NULL;
+ int niter = 0;
+ char str[4096];
+ char*l_argv[1024];
+ int l_argc,l_par;
+ char cmd[MAXITER];
+ int col[MAXITER];
+ svector a[MAXITER];
+ svector x;
+ svector upd;
+ int rval;
+ int i;
+ int j;
+ int rep;
+ int nz;
+ EGioFile_t *fin = 0;
+ char c;
+ int iter;
+ int nsing, *psrow, *pscol;
+ double szeit;
+ double factor_szeit;
+ double ftran_szeit;
+ double btran_szeit;
+ double update_szeit;
+ double factor_zeit = 0.0;
+ double ftran_zeit = 0.0;
+ double btran_zeit = 0.0;
+ double update_zeit = 0.0;
+ double dtmp;
+ QSexactStart();
+ ILLfactor_init_factor_work (&f);
+ for (i = 0; i < MAXITER; i++)
+ {
+ ILLsvector_init (&a[i]);
+ }
+ ILLsvector_init (&x);
+ ILLsvector_init (&upd);
+
+ szeit = ILLutil_zeit ();
+
+ if (ac > 1)
+ {
+ fin = EGioOpen (av[1], "r");
+ if (!fin)
+ {
+ perror (av[1]);
+ fprintf (stderr, "Unable to open %s for input\n", av[1]);
+ return 1;
+ }
+ }
+ else
+ {
+ fin = EGioOpenFILE(stdin);
+ }
+ do{
+ EGioGets(str,4096,fin);
+ EGioNParse(str,1024," ","%#",&i,l_argv);
+ }while(i==0 && !EGioEof(fin));
+ WARNING (i != 3, "Couldn't read dimension, columns and nonzeros, only read"
+ " %d elements", i);
+ dim = atoi(l_argv[0]);
+ ncol = atoi(l_argv[1]);
+ nzcnt = atoi(l_argv[2]);
+ fprintf (stderr, "Using dimension %d columns %d and nonzero %d\n", dim,
+ ncol, nzcnt);
+
+ ILL_SAFE_MALLOC (basis, dim, int);
+ ILL_SAFE_MALLOC (cbeg, ncol, int);
+ ILL_SAFE_MALLOC (clen, ncol, int);
+ ILL_SAFE_MALLOC (cind, nzcnt, int);
+
+ coef = EGlpNumAllocArray (nzcnt);
+
+ do{
+ EGioGets(str,4096,fin);
+ EGioNParse(str,1024," ","%#",&i,l_argv);
+ }while(i==0 && !EGioEof(fin));
+ TESTG((rval=(i!=dim)), CLEANUP, "Wrong format!");
+ for (i = 0; i < dim; i++)
+ {
+ basis[i] = atoi(l_argv[i]);
+ }
+
+ nz = 0;
+ for (i = 0; i < ncol; i++)
+ {
+ cbeg[i] = nz;
+ do
+ {
+ EGioGets(str,4096,fin);
+ EGioNParse(str,1024," ","%#",&l_argc,l_argv);
+ }while(l_argc==0 && !EGioEof(fin));
+ TESTG((rval=(l_argc<1)), CLEANUP, "Wrong format!");
+ clen[i] = l_argv[0];
+ TESTG((rval=(l_argc!= 2*clen[i]+1)), CLEANUP, "Wrong format or too long lines!");
+ for (j = 0; j < clen[i]; j++)
+ {
+ cind[nz] = atoi(l_argv[2*i+1]);
+ dtmp = strtod(l_argv[2*i+2],0);
+ EGlpNumSet (coef[nz], dtmp);
+ nz++;
+ }
+ }
+
+ rval = ILLsvector_alloc (&x, dim);
+ ILL_CLEANUP_IF (rval);
+ rval = ILLsvector_alloc (&upd, dim);
+ ILL_CLEANUP_IF (rval);
+
+ while (niter < MAXITER)
+ {
+ do
+ {
+ EGioGets(str,4096,fin);
+ EGioNParse(str,1024," ","%#",&l_argc,l_argv);
+ }while(l_argc==0 && !EGioEof(fin));
+ l_par = 0;
+ if(l_argc==0) break;
+ TESTG((rval=(l_argc<2)), CLEANUP,"Wrong Format");
+ c = l_argv[l_par++][0];
+ cmd[niter] = c;
+
+ switch (c)
+ {
+ case 'u':
+ col[niter] = atoi(l_argv[l_par++]);
+ case 'F':
+ case 'f':
+ case 'b':
+#ifdef DENSE_READ
+ nzcnt = 0;
+ TESTG((rval=(l_argc!=dim+l_par)), CLEANUP, "Wrng format or too long lines!");
+ for (i = 0; i < dim; i++)
+ {
+ dtmp = strtod(l_argv[l_par++],0);
+ if (dtmp != 0.0)
+ {
+ x.indx[nzcnt] = i;
+ EGlpNumSet (x.coef[nzcnt], dtmp);
+ nzcnt++;
+ }
+ }
+#else
+ nzcnt = atoi(l_argv[l_par++]);
+ TESTG((rval=(l_argc!=2*nzcnt+l_par)), CLEANUP, "Wrong format or too log lines!");
+ for (i = 0; i < nzcnt; i++)
+ {
+ x.indx[i] = atoi(l_argv[l_par++]);
+ dtmp = strtod(l_argv[l_par++],0);
+ EGlpNumSet (x.coef[i], dtmp);
+
+ }
+#endif
+ x.nzcnt = nzcnt;
+ rval = ILLsvector_copy (&x, &a[niter]);
+ ILL_CLEANUP_IF (rval);
+ break;
+ }
+ niter++;
+ }
+
+ printf ("Matrix and iterations read in %.2f seconds\n",
+ ILLutil_zeit () - szeit);
+ fflush (stdout);
+
+ szeit = ILLutil_zeit ();
+
+ for (rep = 0; rep < NREP; rep++)
+ {
+
+ factor_szeit = ILLutil_zeit ();
+
+#if 0
+ ILLfactor_init_factor_work (&f);
+#endif
+
+ rval = ILLfactor_create_factor_work (&f, dim);
+ ILL_CLEANUP_IF (rval);
+
+ rval =
+ ILLfactor (&f, basis, cbeg, clen, cind, coef, &nsing, &psrow, &pscol);
+ ILL_CLEANUP_IF (rval);
+
+ factor_zeit += ILLutil_zeit () - factor_szeit;
+
+ for (iter = 0; iter < niter; iter++)
+ {
+ switch (cmd[iter])
+ {
+ case 'f':
+ ftran_szeit = ILLutil_zeit ();
+ ILLfactor_ftran (&f, &a[iter], &x);
+ ftran_zeit += ILLutil_zeit () - ftran_szeit;
+ break;
+ case 'F':
+ ftran_szeit = ILLutil_zeit ();
+ ILLfactor_ftran_update (&f, &a[iter], &upd, &x);
+ ftran_zeit += ILLutil_zeit () - ftran_szeit;
+ break;
+ case 'b':
+ btran_szeit = ILLutil_zeit ();
+ ILLfactor_btran (&f, &a[iter], &x);
+ btran_zeit += ILLutil_zeit () - btran_szeit;
+ break;
+ case 'u':
+ update_szeit = ILLutil_zeit ();
+ ILLfactor_update (&f, &a[iter], col[iter], &nz);
+ update_zeit += ILLutil_zeit () - update_szeit;
+ break;
+ }
+ }
+ ILLfactor_free_factor_work (&f);
+ }
+ printf ("%d reps of %d steps finished in %.2f seconds\n", rep, niter,
+ ILLutil_zeit () - szeit);
+ printf ("factor: %.2f\n", factor_zeit);
+ printf ("ftran: %.2f\n", ftran_zeit);
+ printf ("btran: %.2f\n", btran_zeit);
+ printf ("update: %.2f\n", update_zeit);
+ fflush (stdout);
+
+ rval = 0;
+
+CLEANUP:
+ if (fin)
+ {
+ EGioClose (fin);
+ }
+ ILLfactor_free_factor_work (&f);
+ ILL_IFFREE (basis, int);
+ ILL_IFFREE (cbeg, int);
+ ILL_IFFREE (clen, int);
+ ILL_IFFREE (cind, int);
+
+ EGlpNumFreeArray (coef);
+ for (i = 0; i < niter; i++)
+ {
+ ILLsvector_free (&a[i]);
+ }
+ ILLsvector_free (&upd);
+ ILLsvector_free (&x);
+ QSexactClear();
+ return rval;
+}
diff --git a/tests/ftest.h b/tests/ftest.h
new file mode 100644
index 0000000..86a0d9b
--- /dev/null
+++ b/tests/ftest.h
@@ -0,0 +1,21 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
diff --git a/tests/solver.c b/tests/solver.c
new file mode 100644
index 0000000..5d3ed11
--- /dev/null
+++ b/tests/solver.c
@@ -0,0 +1,356 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* RCS_INFO = "$RCSfile: solver.c,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:49:52 $"; */
+
+#include "qs_config.h"
+#include "exact.h"
+#include "solver.h"
+#include "iqsutil.h"
+#include "util.h"
+#include "lpdefs.h" /* for PRIMAL_SIMPLEX */
+#include "qstruct.h"
+#include "qsopt.h"
+#include "binary.h"
+#include "editor.h"
+#include "price.h"
+#include "lib.h" /* for ILLmip_binary_dfs */
+
+static char *fname = 0;
+static int lpfile = 0;
+static int solvemip = 0;
+static int interactive = 0;
+static int usescaling = 1;
+static int showversion = 0;
+static int simplexalgo = PRIMAL_SIMPLEX;
+static int pstrategy = QS_PRICE_PSTEEP;
+static int dstrategy = QS_PRICE_DSTEEP;
+static unsigned precision = 128;
+static int printsol = 0;
+static char *readbasis = 0;
+static char *writebasis = 0;
+
+static void usage (
+ char *s),
+ get_ftype (
+ char *name,
+ int *ftype);
+
+#ifdef TEST_FEEDBACK
+static int feedback (
+ FILE * dest,
+ const char *str);
+#endif
+static int parseargs (
+ int ac,
+ char **av);
+
+#ifndef WIN32
+QSLIB_INTERFACE int main ( int ac, char **av);
+int main ( int ac, char **av)
+{
+ int rval;
+ QSopt_ex_version();
+ QSexactStart();
+ rval = solver_main (ac, av);
+ QSexactClear();
+ return rval;
+}
+#endif
+
+QSLIB_INTERFACE int solver_main (
+ int ac,
+ char **av)
+{
+ int rval = 0;
+ QSdata *p = 0;
+ ILLutil_timer timer_solve;
+ ILLutil_timer timer_read;
+ int ftype = 0; /* 0 mps, 1 lp */
+ EGlpNum_t *x = 0;
+ EGlpNum_t val;
+ double szeit;
+
+ rval = parseargs (ac, av);
+ if (rval)
+ ILL_CLEANUP;
+
+ QSset_precision (precision);
+ EGlpNumInitVar (val);
+ if (showversion)
+ {
+ char *buf = 0;
+
+ buf = QSversion ();
+ if (buf == 0)
+ {
+ ILL_CLEANUP;
+ }
+ else
+ {
+ printf ("%s\n", buf);
+ QSfree ((void *) buf);
+ }
+ }
+
+ if (lpfile)
+ {
+ ftype = 1;
+ }
+ else
+ {
+ get_ftype (fname, &ftype);
+ }
+
+ ILLutil_init_timer (&timer_read, "SOLVER_READ");
+ ILLutil_start_timer (&timer_read);
+ if (ftype == 1)
+ {
+ p = QSread_prob ((const char *) fname, "LP");
+ if (p == 0)
+ {
+ fprintf (stderr, "Could not read lp file.\n");
+ rval = 1;
+ ILL_CLEANUP_IF (rval);
+ }
+ }
+ else
+ {
+ p = QSread_prob ((const char *) fname, "MPS");
+ if (p == 0)
+ {
+ fprintf (stderr, "Could not read mps file.\n");
+ rval = 1;
+ ILL_CLEANUP_IF (rval);
+ }
+ }
+
+ if (readbasis)
+ {
+ rval = QSread_and_load_basis (p, (const char *) readbasis);
+ ILL_CLEANUP_IF (rval);
+ }
+ ILLutil_stop_timer (&timer_read, 1);
+ rval = QSset_param (p, QS_PARAM_SIMPLEX_DISPLAY, 1)
+ || QSset_param (p, QS_PARAM_PRIMAL_PRICING, pstrategy)
+ || QSset_param (p, QS_PARAM_DUAL_PRICING, dstrategy)
+ || QSset_param (p, QS_PARAM_SIMPLEX_SCALING, usescaling);
+ ILL_CLEANUP_IF (rval);
+
+ if (interactive)
+ {
+ ILLeditor_init ();
+ ILLeditor (p);
+ goto CLEANUP;
+ }
+
+ szeit = ILLutil_zeit();
+ ILLutil_init_timer (&timer_solve, "SOLVER");
+ ILLutil_start_timer (&timer_solve);
+
+#ifdef TEST_FEEDBACK
+ QSset_reporter (p, (void *) feedback, stdout);
+#endif
+ rval = ILLeditor_solve (p, simplexalgo);
+ ILLutil_stop_timer (&timer_solve, 1);
+ ILL_CLEANUP_IF (rval);
+
+ printf ("ZZ %s %.2f\n", p->lp->O->probname, ILLutil_zeit () - szeit);
+ fflush (stdout);
+
+ if (printsol)
+ x = EGlpNumAllocArray (p->lp->O->nstruct);
+
+ if (solvemip)
+ {
+ rval = ILLmip_bfs (p->lp, &val, x, &(p->itcnt));
+ ILL_CLEANUP_IF (rval);
+ printf ("MIP Objective Value: %.6f\n", EGlpNumToLf (val));
+ fflush (stdout);
+ if (printsol && EGlpNumIsNeqq (val, ILL_MAXDOUBLE) &&
+ EGlpNumIsNeqq (val, ILL_MINDOUBLE))
+ {
+ EGioFile_t*out = EGioOpenFILE(stdout);
+ rval = ILLlib_print_x (out, p->lp, 0, x, 1);
+ EGioClose(out);
+ ILL_CLEANUP_IF (rval);
+ }
+ }
+ else
+ {
+ if (writebasis)
+ {
+ rval = QSwrite_basis (p, 0, writebasis);
+ ILL_CLEANUP_IF (rval);
+ }
+ if (printsol)
+ {
+ EGioFile_t*out = EGioOpenFILE(stdout);
+ rval = ILLlib_print_x (out, p->lp, 0, 0, 1);
+ EGioClose(out);
+ ILL_CLEANUP_IF (rval);
+ }
+ }
+
+CLEANUP:
+ EGlpNumFreeArray (x);
+ QSfree_prob (p);
+ EGlpNumClearVar (val);
+ return rval; /* main return */
+}
+
+static void usage (
+ char *s)
+{
+ char *buf = 0;
+
+ buf = QSversion ();
+ if (buf)
+ {
+ fprintf (stderr, "%s\n", buf);
+ QSfree ((void *) buf);
+ }
+
+ fprintf (stderr, "Usage: %s [- below -] prob_file\n", s);
+ fprintf (stderr, " -b f write basis to file f\n");
+ fprintf (stderr, " -B f read initial basis from file f\n");
+#if 0
+ fprintf (stderr, " -I solve the MIP using BestBound\n");
+ fprintf (stderr, " -E edit problem after solving initial version\n");
+#endif
+ fprintf (stderr, " -L input file is in lp format (default: mps)\n");
+ fprintf (stderr, " -O print the final solution\n");
+ fprintf (stderr, " -p # run primal simplex with pricing rule #\n");
+ fprintf (stderr,
+ " (%d-Dantzig, %d-Devex, %d-Steep (default), %d-Partial\n",
+ QS_PRICE_PDANTZIG, QS_PRICE_PDEVEX, QS_PRICE_PSTEEP,
+ QS_PRICE_PMULTPARTIAL);
+ fprintf (stderr, " -d # run dual simplex with pricing rule #\n");
+ fprintf (stderr, " (%d-Dantzig, %d-Steep, %d-Partial, %d-Devex)\n",
+ QS_PRICE_DDANTZIG, QS_PRICE_DSTEEP, QS_PRICE_DMULTPARTIAL,
+ QS_PRICE_DDEVEX);
+ fprintf (stderr, " -S do NOT scale the initial LP\n");
+ fprintf (stderr, " -v print QSopt version number\n");
+}
+
+static int parseargs (
+ int ac,
+ char **av)
+{
+ int c;
+ int boptind = 1;
+ char *boptarg = 0;
+
+ while ((c =
+ ILLutil_bix_getopt (ac, av, "b:B:d:p:P:IELOSv", &boptind,
+ &boptarg)) != EOF)
+ switch (c)
+ {
+ case 'b':
+ writebasis = boptarg;
+ break;
+ case 'B':
+ readbasis = boptarg;
+ break;
+ case 'P':
+ precision = atoi (boptarg);
+ break;
+ case 'd':
+ simplexalgo = DUAL_SIMPLEX;
+ dstrategy = atoi (boptarg);
+ break;
+#if 0
+ case 'E':
+ interactive = 1;
+ break;
+ case 'I':
+ solvemip = 1;
+ break;
+#endif
+ case 'L':
+ lpfile = 1;
+ break;
+ case 'O':
+ printsol = 1;
+ break;
+ case 'p':
+ simplexalgo = PRIMAL_SIMPLEX;
+ pstrategy = atoi (boptarg);
+ break;
+ case 'S':
+ usescaling = 0;
+ break;
+ case 'v':
+ showversion = 1;
+ break;
+ case '?':
+ default:
+ usage (av[0]);
+ return 1;
+ }
+ if (boptind != (ac - 1))
+ {
+ usage (av[0]);
+ return 1;
+ }
+
+ fname = av[boptind++];
+ fprintf (stderr, "Reading problem from %s\n", fname);
+ return 0;
+}
+
+static void get_ftype (
+ char *name,
+ int *ftype)
+{
+ char *q;
+
+ q = strrchr (name, '.');
+ if (q)
+ {
+ q++;
+ if (!strcmp (q, "lp") || !strcmp (q, "LP"))
+ {
+ *ftype = 1;
+ }
+ else
+ {
+ *ftype = 0;
+ }
+ }
+}
+
+#ifdef TEST_FEEDBACK
+static int feedback (
+ FILE * dest,
+ const char *str)
+{
+ if (str != NULL)
+ {
+ int rc = fprintf ((FILE *) dest, "FEEDBACK: %s", str);
+
+ fflush (dest);
+ return rc;
+ }
+ return 0;
+}
+#endif
diff --git a/tests/solver.h b/tests/solver.h
new file mode 100644
index 0000000..46586e6
--- /dev/null
+++ b/tests/solver.h
@@ -0,0 +1,33 @@
+/****************************************************************************/
+/* */
+/* This file is part of QSopt_ex. */
+/* */
+/* (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash, */
+/* and Daniel Espinoza */
+/* */
+/* Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his */
+/* copyright in QSopt. */
+/* */
+/* This code may be used under the terms of the GNU General Public License */
+/* (Version 2.1 or later) as published by the Free Software Foundation. */
+/* */
+/* Alternatively, use is granted for research purposes only. */
+/* */
+/* It is your choice of which of these two licenses you are operating */
+/* under. */
+/* */
+/* We make no guarantees about the correctness or usefulness of this code. */
+/* */
+/****************************************************************************/
+
+/* $RCSfile: solver.h,v $ $Revision: 1.2 $ $Date: 2003/11/05 16:57:39 $ */
+#ifndef SOLVER_H
+#define SOLVER_H
+
+#include "qsopt.h"
+
+QSLIB_INTERFACE int solver_main (
+ int argc,
+ char **argv);
+
+#endif
diff --git a/tests/test_qs.c b/tests/test_qs.c
new file mode 100644
index 0000000..2952424
--- /dev/null
+++ b/tests/test_qs.c
@@ -0,0 +1,243 @@
+/*
+ * This file is part of QSopt_ex.
+ *
+ * (c) Copyright 2006 by David Applegate, William Cook, Sanjeeb Dash,
+ * and Daniel Espinoza
+ * (c) Copyright 2015 Jon Lund Steffensen <jonlst at gmail.com>
+ *
+ * Sanjeeb Dash ownership of copyright in QSopt_ex is derived from his
+ * copyright in QSopt.
+ *
+ * This code may be used under the terms of the GNU General Public License
+ * (Version 2.1 or later) as published by the Free Software Foundation.
+ *
+ * Alternatively, use is granted for research purposes only.
+ *
+ * It is your choice of which of these two licenses you are operating
+ * under.
+ *
+ * We make no guarantees about the correctness or usefulness of this code.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <gmp.h>
+
+#include "QSopt_ex.h"
+
+/* Number of tests. Must be kept up-to-date manually */
+#define TEST_COUNT 8
+
+/* */
+/* Using QSload_prob to load the following LP problem */
+/* Maximize 3.0x + 2.0y + 4.0z */
+/* Subject to */
+/* 3.0x + 2.0y + 1.0z <= 12.0 */
+/* 5.0x + 1.0y = 10.0 */
+/* x >= 2.0 */
+/* y free */
+/* 1.0 <= z <= 10.0 */
+/* */
+
+static int load_test_problem (mpq_QSprob *p)
+{
+ int i, rval = 0;
+ int cmatcnt[3] = { 2, 2, 1 };
+ int cmatbeg[3] = { 0, 2, 4 };
+ int cmatind[5] = { 0, 1, 0, 1, 0 };
+ char sense[2] = { 'L', 'E' };
+ const char *colnames[3] = { "x", "y", "z" };
+ const char *rownames[2] = { "c1", "c2"};
+ mpq_t cmatval[5];
+ mpq_t obj[3];
+ mpq_t rhs[2];
+ mpq_t lower[3];
+ mpq_t upper[3];
+
+ for (i = 0; i < 5; i++) mpq_init (cmatval[i]);
+ mpq_set_d (cmatval[0], 3.0);
+ mpq_set_d (cmatval[1], 5.0);
+ mpq_set_d (cmatval[2], 2.0);
+ mpq_set_d (cmatval[3], 1.0);
+ mpq_set_d (cmatval[4], 1.0);
+
+ for (i = 0; i < 3; i++) mpq_init (obj[i]);
+ mpq_set_d (obj[0], 3.0);
+ mpq_set_d (obj[1], 2.0);
+ mpq_set_d (obj[2], 4.0);
+
+ for (i = 0; i < 2; i++) mpq_init (rhs[i]);
+ mpq_set_d (rhs[0], 12.0);
+ mpq_set_d (rhs[1], 10.0);
+
+ for (i = 0; i < 3; i++) mpq_init (lower[i]);
+ mpq_set_d (lower[0], 2.0);
+ mpq_set (lower[1], mpq_ILL_MINDOUBLE);
+ mpq_set_d (lower[2], 1.0);
+
+ for (i = 0; i < 3; i++) mpq_init (upper[i]);
+ mpq_set (upper[0], mpq_ILL_MAXDOUBLE);
+ mpq_set (upper[1], mpq_ILL_MAXDOUBLE);
+ mpq_set_d (upper[2], 10.0);
+
+ /* CPXcopylpwnames */
+
+ *p = mpq_QSload_prob ("small", 3, 2, cmatcnt, cmatbeg, cmatind, cmatval,
+ QS_MAX, obj, rhs, sense, lower, upper, colnames,
+ rownames);
+
+ if (*p == (mpq_QSprob) NULL) {
+ fprintf (stderr, "Unable to load the LP problem\n");
+ rval = 1; goto CLEANUP;
+ }
+
+CLEANUP:
+
+ for (i = 0; i < 5; i++) mpq_clear (cmatval[i]);
+ for (i = 0; i < 3; i++) mpq_clear (obj[i]);
+ for (i = 0; i < 2; i++) mpq_clear (rhs[i]);
+ for (i = 0; i < 3; i++) mpq_clear (lower[i]);
+ for (i = 0; i < 3; i++) mpq_clear (upper[i]);
+
+ return rval;
+}
+
+int main (int ac, char **av)
+{
+ int rval = 0, status = 0;
+ int i, nrows = 0, ncols = 0;
+ mpq_t value;
+ mpq_t *x = (mpq_t *) NULL;
+ mpq_t *y = (mpq_t *) NULL;
+ mpq_QSprob p = (mpq_QSprob) NULL;
+ char **colnames = (char **) NULL;
+ char **rownames = (char **) NULL;
+
+ QSexactStart();
+
+ mpq_init (value);
+
+ if (ac > 1) {
+ printf ("Usage: %s\n", *av);
+ rval = EXIT_FAILURE; goto CLEANUP;
+ }
+
+ /* Must call QSexact_set_precision before any other QS function */
+ /* Cannot use mpq_ILL_MAXDOUBLE or mpq_ILL_MINDOUBLE before this call */
+
+ QSexact_set_precision (128);
+
+ /* Print number of tests */
+ printf("1..%u\n", TEST_COUNT);
+
+ /* Test 1 - load test problem */
+ rval = load_test_problem (&p);
+ if (rval) {
+ printf("not ok 1 - Unable to load the LP\n");
+ goto CLEANUP;
+ }
+
+ printf("ok 1 - Loaded test LP problem\n");
+
+ /* Test 2 - get row count */
+ nrows = mpq_QSget_rowcount (p);
+ if (nrows != 2) {
+ printf("not ok 2 - Invalid number of constraints: %d\n", nrows);
+ } else {
+ printf("ok 2 - Got number of constraints\n");
+ }
+
+ /* Test 3 - get col count */
+ ncols = mpq_QSget_colcount (p);
+ if (ncols != 3) {
+ printf("not ok 3 - Invalid number of variables: %d\n", ncols);
+ } else {
+ printf("ok 3 - Got number of variables\n");
+ }
+
+ /* Test 4 - Solve problem */
+ rval = QSexact_solver (p, NULL, NULL, NULL, DUAL_SIMPLEX, &status);
+ if (rval) {
+ printf("not ok 4 - Solver failed\n");
+ goto CLEANUP;
+ }
+ if (status != QS_LP_OPTIMAL) {
+ printf("not ok 4 - Did not find an optimal solution.\n");
+ goto CLEANUP;
+ }
+
+ printf("ok 4 - Solution was found\n");
+
+ /* Test 5 - Get objective value */
+ rval = mpq_QSget_objval (p, &value);
+ if (rval) {
+ printf("not ok 5 - Could not get obj value, error code %d\n", rval);
+ } else {
+ if (mpq_cmp_ui(value, 42, 1) != 0) {
+ printf("not ok 5 - Unexpected obj value: %.6f\n", mpq_get_d(value));
+ } else {
+ printf("ok 5 - The correct objective value was obtained\n");
+ }
+ }
+
+ /* Test 6 - Get variable values */
+ x = (mpq_t *) malloc (ncols * sizeof (mpq_t));
+ for (i = 0; i < ncols; i++) mpq_init (x[i]);
+ rval = mpq_QSget_x_array (p, x);
+ if (rval) {
+ printf("not ok 6 - Could not get x-vector, error code %d\n", rval);
+ } else {
+ colnames = (char **) malloc (ncols * sizeof (char *));
+ mpq_QSget_colnames (p, colnames);
+ printf("ok 6 - Obtained variable values and names\n");
+ }
+
+ /* Test 7 - Get dual values */
+ y = (mpq_t *) malloc (nrows * sizeof (mpq_t));
+ for (i = 0; i < nrows; i++) mpq_init (y[i]);
+ rval = mpq_QSget_pi_array (p, y);
+ if (rval) {
+ printf("not ok 7 - Could not get dual values, error code %d\n", rval);
+ } else {
+ rownames = (char **) malloc (nrows * sizeof (char *));
+ mpq_QSget_rownames (p, rownames);
+ printf("ok 7 - Obtained dual values and contraint names\n");
+ }
+
+ /* Test 8 - Write problem out to /dev/null */
+ rval = mpq_QSwrite_prob (p, "/dev/null", "LP");
+ if (rval) {
+ printf("not ok 8 - Could not write the LP, error code %d\n", rval);
+ } else {
+ printf("ok 8 - LP written to /dev/null\n");
+ }
+
+CLEANUP:
+
+ if (p) mpq_QSfree_prob (p); /* CPXfreeprob */
+
+ mpq_clear (value);
+ if (x) {
+ for (i = 0; i < ncols; i++) mpq_clear (x[i]);
+ free (x);
+ }
+ if (y) {
+ for (i = 0; i < nrows; i++) mpq_clear (y[i]);
+ free (y);
+ }
+ if (rownames) {
+ for (i = 0; i < nrows; i++) if (rownames[i]) free (rownames[i]);
+ free (rownames);
+ }
+ if (colnames) {
+ for (i = 0; i < ncols; i++) if (colnames[i]) free (colnames[i]);
+ free (colnames);
+ }
+
+ QSexactClear();
+ return rval;
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/qsopt-ex.git
More information about the debian-med-commit
mailing list