pax_global_header00006660000000000000000000000064125150305410014506gustar00rootroot0000000000000052 comment=ae24d80816baf3f70cdec1694428b6bbbf2ecf40 qsopt-ex-2.5.10.3/000077500000000000000000000000001251503054100135145ustar00rootroot00000000000000qsopt-ex-2.5.10.3/.gitignore000066400000000000000000000010201251503054100154750ustar00rootroot00000000000000# 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 qsopt-ex-2.5.10.3/.travis.yml000066400000000000000000000004131251503054100156230ustar00rootroot00000000000000language: 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 qsopt-ex-2.5.10.3/Doxyfile000066400000000000000000001404311251503054100152250ustar00rootroot00000000000000# 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 , where is the value of # the FILE_VERSION_FILTER tag, and 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 , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = YES # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = 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 qsopt-ex-2.5.10.3/License.txt000066400000000000000000001045131251503054100156430ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. 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. Copyright (C) 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 . 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: Copyright (C) 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 . 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 . qsopt-ex-2.5.10.3/Makefile.am000066400000000000000000000147631251503054100155630ustar00rootroot00000000000000 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) qsopt-ex-2.5.10.3/NEWS.md000066400000000000000000000035241251503054100146160ustar00rootroot00000000000000 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 (``). * 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. qsopt-ex-2.5.10.3/README.md000066400000000000000000000052621251503054100150000ustar00rootroot00000000000000 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). qsopt-ex-2.5.10.3/bootstrap000077500000000000000000000001411251503054100154530ustar00rootroot00000000000000#!/bin/sh # change to root directory cd $(dirname "$0") autoreconf --force --install --verbose qsopt-ex-2.5.10.3/configure.ac000066400000000000000000000074441251503054100160130ustar00rootroot00000000000000# -*- 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} " qsopt-ex-2.5.10.3/contrib/000077500000000000000000000000001251503054100151545ustar00rootroot00000000000000qsopt-ex-2.5.10.3/contrib/debian/000077500000000000000000000000001251503054100163765ustar00rootroot00000000000000qsopt-ex-2.5.10.3/contrib/debian/changelog000066400000000000000000000002241251503054100202460ustar00rootroot00000000000000qsopt-ex (2.5.10.2-0ubuntu1) precise; urgency=low * Initial release -- Jon Lund Steffensen Sun, 15 Mar 2015 22:49:09 +0000 qsopt-ex-2.5.10.3/contrib/debian/compat000066400000000000000000000000021251503054100175740ustar00rootroot000000000000008 qsopt-ex-2.5.10.3/contrib/debian/control000066400000000000000000000037711251503054100200110ustar00rootroot00000000000000Source: qsopt-ex Priority: extra Maintainer: Jon Lund Steffensen Build-Depends: debhelper (>= 8.0.0), autotools-dev, libgmp-dev Standards-Version: 3.9.2 Section: libs Homepage: https://github.com/jonls/qsopt-ex #Vcs-Git: git://git.debian.org/collab-maint/qsopt-ex.git #Vcs-Browser: http://git.debian.org/?p=collab-maint/qsopt-ex.git;a=summary Package: qsopt-ex-dev Section: libdevel Architecture: any Depends: qsopt-ex2 (= ${binary:Version}), ${misc:Depends} Description: Exact linear programming solver This is a fork of QSopt_ex, originally released by Daniel Espinoza et al. version 2.5.10 under the GPL 3 (or later). 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. . This package contains the development files. Package: qsopt-ex-esolver Section: math Architecture: any Depends: qsopt-ex2 (= ${binary:Version}), ${shlibs:Depends}, ${misc:Depends} Description: Exact linear programming solver This is a fork of QSopt_ex, originally released by Daniel Espinoza et al. version 2.5.10 under the GPL 3 (or later). 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. . This package contains the esolver program. Package: qsopt-ex2 Section: libs Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Description: Exact linear programming solver This is a fork of QSopt_ex, originally released by Daniel Espinoza et al. version 2.5.10 under the GPL 3 (or later). 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. . This package contains the main library. qsopt-ex-2.5.10.3/contrib/debian/copyright000066400000000000000000000016741251503054100203410ustar00rootroot00000000000000Format: http://dep.debian.net/deps/dep5 Upstream-Name: qsopt-ex Source: https://github.com/jonls/qsopt-ex Files: debian/* Copyright: 2015 Jon Lund Steffensen License: GPL-3+ This package is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. . This package 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 . On Debian systems, the complete text of the GNU General Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". qsopt-ex-2.5.10.3/contrib/debian/docs000066400000000000000000000000121251503054100172420ustar00rootroot00000000000000README.md qsopt-ex-2.5.10.3/contrib/debian/qsopt-ex-dev.dirs000066400000000000000000000000241251503054100216110ustar00rootroot00000000000000usr/lib usr/include qsopt-ex-2.5.10.3/contrib/debian/qsopt-ex-dev.install000066400000000000000000000000551251503054100223220ustar00rootroot00000000000000usr/include/* usr/lib/lib*.a usr/lib/lib*.so qsopt-ex-2.5.10.3/contrib/debian/qsopt-ex-esolver.dirs000066400000000000000000000000101251503054100225050ustar00rootroot00000000000000usr/bin qsopt-ex-2.5.10.3/contrib/debian/qsopt-ex-esolver.install000066400000000000000000000000201251503054100232130ustar00rootroot00000000000000usr/bin/esolver qsopt-ex-2.5.10.3/contrib/debian/qsopt-ex2.dirs000066400000000000000000000000101251503054100211120ustar00rootroot00000000000000usr/lib qsopt-ex-2.5.10.3/contrib/debian/qsopt-ex2.install000066400000000000000000000000221251503054100216220ustar00rootroot00000000000000usr/lib/lib*.so.* qsopt-ex-2.5.10.3/contrib/debian/rules000077500000000000000000000006721251503054100174630ustar00rootroot00000000000000#!/usr/bin/make -f # -*- makefile -*- # Sample debian/rules that uses debhelper. # This file was originally written by Joey Hess and Craig Small. # As a special exception, when this file is copied by dh-make into a # dh-make output file, you may use that output file without restriction. # This special exception was added by Craig Small in version 0.37 of dh-make. # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 %: dh $@ qsopt-ex-2.5.10.3/contrib/debian/source/000077500000000000000000000000001251503054100176765ustar00rootroot00000000000000qsopt-ex-2.5.10.3/contrib/debian/source/format000066400000000000000000000000141251503054100211040ustar00rootroot000000000000003.0 (quilt) qsopt-ex-2.5.10.3/contrib/fedora/000077500000000000000000000000001251503054100164145ustar00rootroot00000000000000qsopt-ex-2.5.10.3/contrib/fedora/qsopt_ex.spec000066400000000000000000000032751251503054100211410ustar00rootroot00000000000000Summary: An exact, linear programming solver Name: qsopt_ex Version: 2.5.10.2 Release: 1%{dist} License: GPLv3+ Group: Applications/Engineering URL: https://github.com/jonls/qsopt-ex Source0: https://github.com/jonls/qsopt-ex/releases/download/v%{version}/%{name}-%{version}.tar.xz BuildRequires: chrpath BuildRequires: libtool BuildRequires: zlib-devel BuildRequires: bzip2-devel BuildRequires: gmp-devel %description Exact linear programming solver. This is a fork of QSopt_ex by Daniel Espinoza et al. version 2.5.10. 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. This is the base library. %package -n %{name}-devel Summary: Development files for qsopt_ex Group: Applications/Engineering Requires: %{name} = %{version}-%{release} %description -n %{name}-devel Development files for qsopt_ex, an exact linear programming solver. %prep %setup -q %build %configure --disable-static make %{?_smp_mflags} V=1 %install rm -rf %{buildroot} make DESTDIR=%{buildroot} install INSTALL="install -p" chrpath --delete %{buildroot}%{_bindir}/esolver rm -f %{buildroot}%{_libdir}/libqsopt_ex.la %post -p /sbin/ldconfig %postun -p /sbin/ldconfig %files %defattr(-,root,root,-) %doc README.md NEWS.md License.txt %{_bindir}/esolver %{_libdir}/libqsopt_ex.so.2 %{_libdir}/libqsopt_ex.so.2.0.2 %files -n %{name}-devel %{_libdir}/libqsopt_ex.so %{_includedir}/qsopt_ex/ %changelog * Tue Dec 16 2014 Jon Lund Steffensen - - Update for release 2.5.10.2 * Sat Nov 29 2014 Jon Lund Steffensen - - Initial build. qsopt-ex-2.5.10.3/contrib/macports/000077500000000000000000000000001251503054100170045ustar00rootroot00000000000000qsopt-ex-2.5.10.3/contrib/macports/math/000077500000000000000000000000001251503054100177355ustar00rootroot00000000000000qsopt-ex-2.5.10.3/contrib/macports/math/qsopt_ex/000077500000000000000000000000001251503054100215775ustar00rootroot00000000000000qsopt-ex-2.5.10.3/contrib/macports/math/qsopt_ex/Portfile000066400000000000000000000015401251503054100233060ustar00rootroot00000000000000# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4 # $Id$ PortSystem 1.0 name qsopt_ex version 2.5.10.2 categories math platforms darwin license GPL-3+ maintainers gmail.com:jonls description Exact linear programming solver long_description QSopt_ex is a fast, exact linear programming solver. homepage https://github.com/jonls/qsopt-ex master_sites https://github.com/jonls/qsopt-ex/releases/download/v${version}/ use_xz yes checksums rmd160 8d2c9ea54ccb564e732ea0344580f8750ae03d79 \ sha256 37a4f0b4dad62e75108dc876e0c23da2a12a601dfc7e2f3e7752104d097bb14c depends_build port:libtool depends_lib port:zlib port:gmp qsopt-ex-2.5.10.3/esolver/000077500000000000000000000000001251503054100151735ustar00rootroot00000000000000qsopt-ex-2.5.10.3/esolver/esolver.c000066400000000000000000000257141251503054100170270ustar00rootroot00000000000000/* ========================================================================= */ /* 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 #include #include #include #include #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 */ } qsopt-ex-2.5.10.3/m4/000077500000000000000000000000001251503054100140345ustar00rootroot00000000000000qsopt-ex-2.5.10.3/m4/README000066400000000000000000000002511251503054100147120ustar00rootroot00000000000000This 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. qsopt-ex-2.5.10.3/qsopt_ex/000077500000000000000000000000001251503054100153565ustar00rootroot00000000000000qsopt-ex-2.5.10.3/qsopt_ex/QSopt_ex.h000066400000000000000000000056061251503054100173000ustar00rootroot00000000000000/* 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 */ #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 */ qsopt-ex-2.5.10.3/qsopt_ex/QSopt_ex_version.c000066400000000000000000000021041251503054100210260ustar00rootroot00000000000000/* 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 */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include "logging-private.h" void QSopt_ex_version(void) { QSlog("Using %s %s", PACKAGE_NAME, PACKAGE_VERSION); } qsopt-ex-2.5.10.3/qsopt_ex/QSopt_ex_version.h000066400000000000000000000020031251503054100210310ustar00rootroot00000000000000/* 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 */ #ifndef QSOPT_EX_VERSION_H #define QSOPT_EX_VERSION_H void QSopt_ex_version(void); #endif /* !QSOPT_EX_VERSION_H */ qsopt-ex-2.5.10.3/qsopt_ex/allocrus.c000066400000000000000000000247241251503054100173570ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 #include #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; } } qsopt-ex-2.5.10.3/qsopt_ex/allocrus.h000066400000000000000000000323421251503054100173570ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 #include #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 qsopt-ex-2.5.10.3/qsopt_ex/basicdefs.h000066400000000000000000000265061251503054100174630ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 qsopt-ex-2.5.10.3/qsopt_ex/basis.c000066400000000000000000001155211251503054100166300ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 #include #include #include #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 } qsopt-ex-2.5.10.3/qsopt_ex/basis.h000066400000000000000000000073651251503054100166430ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 */ qsopt-ex-2.5.10.3/qsopt_ex/bgetopt.c000066400000000000000000000124731251503054100171750ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 #include #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); } } } qsopt-ex-2.5.10.3/qsopt_ex/bgetopt.h000066400000000000000000000043141251503054100171750ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 qsopt-ex-2.5.10.3/qsopt_ex/binary.c000066400000000000000000001363731251503054100170230ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 #include #include #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)); } } qsopt-ex-2.5.10.3/qsopt_ex/binary.h000066400000000000000000000043551251503054100170220ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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); qsopt-ex-2.5.10.3/qsopt_ex/dheaps_i.c000066400000000000000000000301771251503054100173060ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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; } qsopt-ex-2.5.10.3/qsopt_ex/dheaps_i.h000066400000000000000000000057051251503054100173120ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 qsopt-ex-2.5.10.3/qsopt_ex/dstruct.c000066400000000000000000000307271251503054100172230ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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"); } } } qsopt-ex-2.5.10.3/qsopt_ex/dstruct.h000066400000000000000000000125441251503054100172250ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 */ qsopt-ex-2.5.10.3/qsopt_ex/editor.c000066400000000000000000000500551251503054100170150ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 #include #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--; } } qsopt-ex-2.5.10.3/qsopt_ex/editor.h000066400000000000000000000037631251503054100170260ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 qsopt-ex-2.5.10.3/qsopt_ex/eg_elist.h000066400000000000000000000240121251503054100173210ustar00rootroot00000000000000/* 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 qsopt-ex-2.5.10.3/qsopt_ex/eg_exact.h000066400000000000000000000064541251503054100173170ustar00rootroot00000000000000/* 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

This is a joint project of Daniel Espinoza, William Cook, Sanjeeb Dash and David Applegate. Also, Kati Wolter has contributed with bug-fixes, bug-reports and special functionality for SCIP exact.

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.

It relies heavilly on the GNUMP library, 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 QSopt, 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 here (pdf), and a longer description (which is part of my Ph.D. thesis) can be found here Much of the functionality used in QSopt-Exact comes from EGlib.

You can see the documentation or download the program source.

We also have made available binaries for linux 32 bit and for linux 64 bit

Finally, many thanks to all people that have contributed with bug-reports, comments, and help.

* */ qsopt-ex-2.5.10.3/qsopt_ex/eg_exutil.c000066400000000000000000000333371251503054100175200ustar00rootroot00000000000000/* ========================================================================= */ /* 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 */ qsopt-ex-2.5.10.3/qsopt_ex/eg_exutil.h000066400000000000000000000341401251503054100175160ustar00rootroot00000000000000/* ========================================================================= */ /* 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 #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 using continued fractions method 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 qsopt-ex-2.5.10.3/qsopt_ex/eg_io.c000066400000000000000000000416771251503054100166230ustar00rootroot00000000000000/* 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 #endif #include #include #include #include #include #ifdef HAVE_LIBBZ2 # include #endif #ifdef HAVE_LIBZ # include #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; } }/* ========================================================================= */ /** @} */ qsopt-ex-2.5.10.3/qsopt_ex/eg_io.h000066400000000000000000000374661251503054100166310ustar00rootroot00000000000000/* 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 qsopt-ex-2.5.10.3/qsopt_ex/eg_lpnum.c000066400000000000000000000633241251503054100173400ustar00rootroot00000000000000/* 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 #include #include #include #include #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); } /* ========================================================================= */ /** @} */ qsopt-ex-2.5.10.3/qsopt_ex/eg_lpnum.dbl.h000066400000000000000000000505351251503054100201050ustar00rootroot00000000000000/* 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 #include #include #include #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 qsopt-ex-2.5.10.3/qsopt_ex/eg_lpnum.h000066400000000000000000000773041251503054100173500ustar00rootroot00000000000000/* 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 #include #include /* ========================================================================= */ /** @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 qsopt-ex-2.5.10.3/qsopt_ex/eg_lpnum.mpf.h000066400000000000000000000601111251503054100201150ustar00rootroot00000000000000/* 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 #include #include #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 qsopt-ex-2.5.10.3/qsopt_ex/eg_lpnum.mpq.h000066400000000000000000000575401251503054100201440ustar00rootroot00000000000000/* 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 #include #include #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 qsopt-ex-2.5.10.3/qsopt_ex/eg_macros.c000066400000000000000000000111101251503054100174530ustar00rootroot00000000000000/* ========================================================================= */ /* 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 #include #include #include #include #include #include #include #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 */ qsopt-ex-2.5.10.3/qsopt_ex/eg_macros.h000066400000000000000000000311651251503054100174740ustar00rootroot00000000000000/* ========================================================================= */ /* 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 #include #include #include /* ========================================================================= */ /** @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 qsopt-ex-2.5.10.3/qsopt_ex/eg_mem.h000066400000000000000000000221301251503054100167560ustar00rootroot00000000000000/* 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 qsopt-ex-2.5.10.3/qsopt_ex/eg_memslab.c000066400000000000000000000253121251503054100176200ustar00rootroot00000000000000/* 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 #include #include #include /* 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 } /* ========================================================================= */ qsopt-ex-2.5.10.3/qsopt_ex/eg_memslab.h000066400000000000000000000437041251503054100176320ustar00rootroot00000000000000/* 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 #include #include #include #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 qsopt-ex-2.5.10.3/qsopt_ex/eg_nummacros.h000066400000000000000000000061571251503054100202170ustar00rootroot00000000000000/* 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 qsopt-ex-2.5.10.3/qsopt_ex/eg_numutil.c000066400000000000000000000062761251503054100177050ustar00rootroot00000000000000/* 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]); } /* ========================================================================= */ /** @} */ qsopt-ex-2.5.10.3/qsopt_ex/eg_numutil.h000066400000000000000000000105241251503054100177010ustar00rootroot00000000000000/* 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 qsopt-ex-2.5.10.3/qsopt_ex/eg_timer.h000066400000000000000000000131311251503054100173210ustar00rootroot00000000000000/* 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 #include #include #include #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 qsopt-ex-2.5.10.3/qsopt_ex/exact.c000066400000000000000000001522441251503054100166360ustar00rootroot00000000000000/* ========================================================================= */ /* 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 #include #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 */ qsopt-ex-2.5.10.3/qsopt_ex/exact.h000066400000000000000000000365711251503054100166470ustar00rootroot00000000000000/* ========================================================================= */ /* 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 #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 qsopt-ex-2.5.10.3/qsopt_ex/except.c000066400000000000000000000042631251503054100170170ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 #include #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; qsopt-ex-2.5.10.3/qsopt_ex/except.h000066400000000000000000000130511251503054100170170ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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: + "\n" * * with_source_info == 1: if (fct != NULL) * + " in function \n"; * else * + " in file 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 qsopt-ex-2.5.10.3/qsopt_ex/factor.c000066400000000000000000003563011251503054100170100ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 #include #include #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; } qsopt-ex-2.5.10.3/qsopt_ex/factor.h000066400000000000000000000131461251503054100170120ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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_ */ qsopt-ex-2.5.10.3/qsopt_ex/fct.c000066400000000000000000002041531251503054100163030ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 qsopt-ex-2.5.10.3/qsopt_ex/fct.h000066400000000000000000000211051251503054100163020ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 */ qsopt-ex-2.5.10.3/qsopt_ex/format.c000066400000000000000000000142511251503054100170150ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 #include #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; } qsopt-ex-2.5.10.3/qsopt_ex/format.h000066400000000000000000000116661251503054100170310ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 #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 qsopt-ex-2.5.10.3/qsopt_ex/lib.c000066400000000000000000003000711251503054100162710ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 #include #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 qsopt-ex-2.5.10.3/qsopt_ex/lib.h000066400000000000000000000256401251503054100163040ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 */ qsopt-ex-2.5.10.3/qsopt_ex/logging-private.h000066400000000000000000000216251251503054100206330ustar00rootroot00000000000000/* logging - Private functions for logging/error reporting * * Copyright (C) 2015 Jon Lund Steffensen * * 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 . * */ #ifndef QS_LOGGING_PRIVATE_H__ #define QS_LOGGING_PRIVATE_H__ #include #include #include 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__ */ qsopt-ex-2.5.10.3/qsopt_ex/logging.c000066400000000000000000000033761251503054100171610ustar00rootroot00000000000000/* logging - Functions for logging/error reporting * * Copyright (C) 2015 Jon Lund Steffensen * * 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 . * */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #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); } qsopt-ex-2.5.10.3/qsopt_ex/logging.h000066400000000000000000000017121251503054100171560ustar00rootroot00000000000000/* logging - Functions for logging/error reporting * * Copyright (C) 2015 Jon Lund Steffensen * * 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 . * */ #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__ */ qsopt-ex-2.5.10.3/qsopt_ex/lp.c000066400000000000000000001067001251503054100161410ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 #include #include #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" * make sure names contain solely the characters: * [a-zA-Z0-9] and ! " # $ % & ( ) / , . ; ? @ _ ` ' { } | ~ * rename names with 'bad' chars to */ 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, C, or c_0, c_1, c_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); } qsopt-ex-2.5.10.3/qsopt_ex/lp.h000066400000000000000000000066021251503054100161460ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 qsopt-ex-2.5.10.3/qsopt_ex/lpdata.c000066400000000000000000000651361251503054100170020ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 #include #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; } qsopt-ex-2.5.10.3/qsopt_ex/lpdata.h000066400000000000000000000261571251503054100170070ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 */ qsopt-ex-2.5.10.3/qsopt_ex/lpdefs.h000066400000000000000000000241521251503054100170100ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 */ qsopt-ex-2.5.10.3/qsopt_ex/mps.c000066400000000000000000001102341251503054100163220ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 #include #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; } qsopt-ex-2.5.10.3/qsopt_ex/mps.h000066400000000000000000000053701251503054100163330ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 qsopt-ex-2.5.10.3/qsopt_ex/names.c000066400000000000000000000053761251503054100166400ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 #include #include #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; } qsopt-ex-2.5.10.3/qsopt_ex/names.h000066400000000000000000000035611251503054100166370ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 qsopt-ex-2.5.10.3/qsopt_ex/presolve.c000066400000000000000000001671641251503054100174000ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 #include #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); } } qsopt-ex-2.5.10.3/qsopt_ex/presolve.h000066400000000000000000000047301251503054100173720ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 */ qsopt-ex-2.5.10.3/qsopt_ex/price.c000066400000000000000000001314061251503054100166310ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 qsopt-ex-2.5.10.3/qsopt_ex/price.h000066400000000000000000000175421251503054100166420ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 */ qsopt-ex-2.5.10.3/qsopt_ex/priority.c000066400000000000000000000253311251503054100174070ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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); } qsopt-ex-2.5.10.3/qsopt_ex/priority.h000066400000000000000000000061711251503054100174150ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 qsopt-ex-2.5.10.3/qsopt_ex/qs_config.h000066400000000000000000000050201251503054100174740ustar00rootroot00000000000000/* 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 qsopt-ex-2.5.10.3/qsopt_ex/qsopt.c000066400000000000000000002653041251503054100167020ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 #include #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; } qsopt-ex-2.5.10.3/qsopt_ex/qsopt.h000066400000000000000000000502671251503054100167070ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 #include #include #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 */ qsopt-ex-2.5.10.3/qsopt_ex/qstruct.h000066400000000000000000000047461251503054100172470ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 */ qsopt-ex-2.5.10.3/qsopt_ex/ratio.c000066400000000000000000001162751251503054100166540ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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; } qsopt-ex-2.5.10.3/qsopt_ex/ratio.h000066400000000000000000000057731251503054100166610ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 */ qsopt-ex-2.5.10.3/qsopt_ex/rawlp.c000066400000000000000000001313211251503054100166500ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 #include #include #include #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; } qsopt-ex-2.5.10.3/qsopt_ex/rawlp.h000066400000000000000000000226001251503054100166540ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 qsopt-ex-2.5.10.3/qsopt_ex/read_lp.c000066400000000000000000000443301251503054100171340ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 #include #include #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"); } qsopt-ex-2.5.10.3/qsopt_ex/read_lp.h000066400000000000000000000140501251503054100171350ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 qsopt-ex-2.5.10.3/qsopt_ex/read_mps.c000066400000000000000000000304201251503054100173130ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 #include #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); } } qsopt-ex-2.5.10.3/qsopt_ex/read_mps.h000066400000000000000000000077571251503054100173410ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 qsopt-ex-2.5.10.3/qsopt_ex/reader.c000066400000000000000000000155741251503054100170000ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 qsopt-ex-2.5.10.3/qsopt_ex/reader.h000066400000000000000000000035211251503054100167720ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 qsopt-ex-2.5.10.3/qsopt_ex/readline.c000066400000000000000000000046541251503054100173160ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 #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 */ qsopt-ex-2.5.10.3/qsopt_ex/readline.h000066400000000000000000000055401251503054100173160ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 qsopt-ex-2.5.10.3/qsopt_ex/reporter.c000066400000000000000000000053561251503054100173750ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 #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 qsopt-ex-2.5.10.3/qsopt_ex/reporter.h000066400000000000000000000045361251503054100174010ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 qsopt-ex-2.5.10.3/qsopt_ex/simplex.c000066400000000000000000002577661251503054100172320ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 #include #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 qsopt-ex-2.5.10.3/qsopt_ex/simplex.h000066400000000000000000000077701251503054100172230ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 */ qsopt-ex-2.5.10.3/qsopt_ex/sortrus.c000066400000000000000000000226611251503054100172520ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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< 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); } qsopt-ex-2.5.10.3/qsopt_ex/sortrus.h000066400000000000000000000045241251503054100172550ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 qsopt-ex-2.5.10.3/qsopt_ex/sortrus_common.c000066400000000000000000000253361251503054100206240ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 #include #include "qs_config.h" #include "util.h" #include "except.h" #define BITS_PER_PASS (8) #define NBINS (1<= 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; } } qsopt-ex-2.5.10.3/qsopt_ex/sortrus_common.h000066400000000000000000000050151251503054100206210ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 qsopt-ex-2.5.10.3/qsopt_ex/stddefs.h000066400000000000000000000037041251503054100171670ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 */ qsopt-ex-2.5.10.3/qsopt_ex/symtab.c000066400000000000000000000516721251503054100170340ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 #include #include #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 qsopt-ex-2.5.10.3/qsopt_ex/symtab.h000066400000000000000000000103611251503054100170270ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 #include /* 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 */ qsopt-ex-2.5.10.3/qsopt_ex/trace.h000066400000000000000000000042141251503054100166260ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 qsopt-ex-2.5.10.3/qsopt_ex/urandom.c000066400000000000000000000160761251503054100172010ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 */ qsopt-ex-2.5.10.3/qsopt_ex/urandom.h000066400000000000000000000052411251503054100171760ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 qsopt-ex-2.5.10.3/qsopt_ex/util.c000066400000000000000000000211101251503054100164720ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 #include #include #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; } qsopt-ex-2.5.10.3/qsopt_ex/util.h000066400000000000000000000134651251503054100165150ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 */ qsopt-ex-2.5.10.3/qsopt_ex/write_lp.c000066400000000000000000000145111251503054100173510ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 #include #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; } qsopt-ex-2.5.10.3/qsopt_ex/write_lp.h000066400000000000000000000065021251503054100173570ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 qsopt-ex-2.5.10.3/qsopt_ex/zeit.c000066400000000000000000000236371251503054100165100ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 #include #include #include #include "logging-private.h" #include "util.h" #ifdef HAVE_GETRUSAGE #ifdef HAVE_SYS_RESOURCE_H # include #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 #endif #ifdef HAVE_SYS_TIMES_H # include #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; } qsopt-ex-2.5.10.3/qsopt_ex/zeit.h000066400000000000000000000050461251503054100165070ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 qsopt-ex-2.5.10.3/tap-driver.sh000077500000000000000000000460101251503054100161310ustar00rootroot00000000000000#! /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 . # 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 or send patches to # . 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 < # 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 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: qsopt-ex-2.5.10.3/tests/000077500000000000000000000000001251503054100146565ustar00rootroot00000000000000qsopt-ex-2.5.10.3/tests/eg_lpnum_ex.c000066400000000000000000000224151251503054100173300ustar00rootroot00000000000000/* 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; } /* ========================================================================= */ /** @} */ qsopt-ex-2.5.10.3/tests/eg_sloan.c000066400000000000000000000155531251503054100166220ustar00rootroot00000000000000 #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #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; } qsopt-ex-2.5.10.3/tests/eg_sloan.h000066400000000000000000000002031251503054100166110ustar00rootroot00000000000000#ifndef __SLOAN_LP__ #define __SLOAN_LP__ #include #if OS == LINUX #include #endif #include "exact.h" #endif qsopt-ex-2.5.10.3/tests/ftest.c000066400000000000000000000166711251503054100161620ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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; } qsopt-ex-2.5.10.3/tests/ftest.h000066400000000000000000000031731251503054100161600ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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. */ /* */ /****************************************************************************/ qsopt-ex-2.5.10.3/tests/solver.c000066400000000000000000000200771251503054100163420ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 qsopt-ex-2.5.10.3/tests/solver.h000066400000000000000000000035021251503054100163410ustar00rootroot00000000000000/****************************************************************************/ /* */ /* 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 qsopt-ex-2.5.10.3/tests/test_qs.c000066400000000000000000000160461251503054100165130ustar00rootroot00000000000000/* * 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 * * 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 #include #include #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; }